001/*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2013 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * SonarQube is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020package org.sonar.api.issue.internal;
021
022import com.google.common.base.Splitter;
023import com.google.common.base.Strings;
024import com.google.common.collect.Maps;
025
026import javax.annotation.CheckForNull;
027import javax.annotation.Nullable;
028import java.io.Serializable;
029import java.util.Date;
030import java.util.Map;
031
032/**
033 * PLUGINS MUST NOT USE THIS CLASS, EXCEPT FOR UNIT TESTING.
034 *
035 * @since 3.6
036 */
037public class FieldDiffs implements Serializable {
038
039  public static final Splitter FIELDS_SPLITTER = Splitter.on(',').omitEmptyStrings();
040
041  private String userLogin;
042  private Date createdAt, updatedAt;
043  private final Map<String, Diff> diffs = Maps.newLinkedHashMap();
044
045  public Map<String, Diff> diffs() {
046    return diffs;
047  }
048
049  public Diff get(String field) {
050    return diffs.get(field);
051  }
052
053  @CheckForNull
054  public String userLogin() {
055    return userLogin;
056  }
057
058  public FieldDiffs setUserLogin(@Nullable String s) {
059    this.userLogin = s;
060    return this;
061  }
062
063  public Date createdAt() {
064    return createdAt;
065  }
066
067  public FieldDiffs setCreatedAt(Date d) {
068    this.createdAt = d;
069    return this;
070  }
071
072  public Date updatedAt() {
073    return updatedAt;
074  }
075
076  public FieldDiffs setUpdatedAt(Date d) {
077    this.updatedAt = d;
078    return this;
079  }
080
081
082  @SuppressWarnings("unchecked")
083  public FieldDiffs setDiff(String field, @Nullable Serializable oldValue, @Nullable Serializable newValue) {
084    Diff diff = diffs.get(field);
085    if (diff == null) {
086      diff = new Diff(oldValue, newValue);
087      diffs.put(field, diff);
088    } else {
089      diff.setNewValue(newValue);
090    }
091    return this;
092  }
093
094  @Override
095  public String toString() {
096    StringBuilder sb = new StringBuilder();
097    boolean notFirst = false;
098    for (Map.Entry<String, Diff> entry : diffs.entrySet()) {
099      if (notFirst) {
100        sb.append(',');
101      } else {
102        notFirst = true;
103      }
104      sb.append(entry.getKey());
105      sb.append('=');
106      sb.append(entry.getValue().toString());
107    }
108    return sb.toString();
109  }
110
111  public static FieldDiffs parse(@Nullable String s) {
112    FieldDiffs diffs = new FieldDiffs();
113    if (!Strings.isNullOrEmpty(s)) {
114      Iterable<String> fields = FIELDS_SPLITTER.split(s);
115      for (String field : fields) {
116        String[] keyValues = field.split("=");
117        if (keyValues.length == 2) {
118          String[] values = keyValues[1].split("\\|");
119          String oldValue = "";
120          String newValue = "";
121          if(values.length == 1) {
122            newValue = Strings.nullToEmpty(values[0]);
123          } else if(values.length == 2) {
124            oldValue = Strings.nullToEmpty(values[0]);
125            newValue = Strings.nullToEmpty(values[1]);
126          }
127          diffs.setDiff(keyValues[0], oldValue, newValue);
128        } else {
129          diffs.setDiff(keyValues[0], "", "");
130        }
131      }
132    }
133    return diffs;
134  }
135
136  public static class Diff<T extends Serializable> implements Serializable {
137    private T oldValue, newValue;
138
139    public Diff(@Nullable T oldValue, @Nullable T newValue) {
140      this.oldValue = oldValue;
141      this.newValue = newValue;
142    }
143
144    public T oldValue() {
145      return oldValue;
146    }
147
148    public T newValue() {
149      return newValue;
150    }
151
152    void setNewValue(T t) {
153      this.newValue = t;
154    }
155
156    @Override
157    public String toString() {
158      //TODO escape , and | characters
159      StringBuilder sb = new StringBuilder();
160      if(newValue != null) {
161        if(oldValue != null) {
162          sb.append(oldValue.toString());
163          sb.append('|');
164        }
165        sb.append(newValue.toString());
166      }
167      return sb.toString();
168    }
169  }
170}