001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 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     */
020    package org.sonar.api.issue.internal;
021    
022    import com.google.common.base.Splitter;
023    import com.google.common.base.Strings;
024    import com.google.common.collect.Maps;
025    
026    import javax.annotation.CheckForNull;
027    import javax.annotation.Nullable;
028    
029    import java.io.Serializable;
030    import java.util.Date;
031    import java.util.Map;
032    
033    /**
034     * PLUGINS MUST NOT USE THIS CLASS, EXCEPT FOR UNIT TESTING.
035     *
036     * @since 3.6
037     */
038    public class FieldDiffs implements Serializable {
039    
040      public static final Splitter FIELDS_SPLITTER = Splitter.on(',').omitEmptyStrings();
041    
042      private String issueKey;
043      private String userLogin;
044      private Date creationDate;
045    
046      private final Map<String, Diff> diffs = Maps.newLinkedHashMap();
047    
048      public Map<String, Diff> diffs() {
049        return diffs;
050      }
051    
052      public Diff get(String field) {
053        return diffs.get(field);
054      }
055    
056      @CheckForNull
057      public String userLogin() {
058        return userLogin;
059      }
060    
061      public FieldDiffs setUserLogin(@Nullable String s) {
062        this.userLogin = s;
063        return this;
064      }
065    
066      public Date creationDate() {
067        return creationDate;
068      }
069    
070      public FieldDiffs setCreationDate(Date creationDate) {
071        this.creationDate = creationDate;
072        return this;
073      }
074    
075      public String issueKey() {
076        return issueKey;
077      }
078    
079      public FieldDiffs setIssueKey(String issueKey) {
080        this.issueKey = issueKey;
081        return this;
082      }
083    
084      @SuppressWarnings("unchecked")
085      public FieldDiffs setDiff(String field, @Nullable Serializable oldValue, @Nullable Serializable newValue) {
086        Diff diff = diffs.get(field);
087        if (diff == null) {
088          diff = new Diff(oldValue, newValue);
089          diffs.put(field, diff);
090        } else {
091          diff.setNewValue(newValue);
092        }
093        return this;
094      }
095    
096      @Override
097      public String toString() {
098        StringBuilder sb = new StringBuilder();
099        boolean notFirst = false;
100        for (Map.Entry<String, Diff> entry : diffs.entrySet()) {
101          if (notFirst) {
102            sb.append(',');
103          } else {
104            notFirst = true;
105          }
106          sb.append(entry.getKey());
107          sb.append('=');
108          sb.append(entry.getValue().toString());
109        }
110        return sb.toString();
111      }
112    
113      public static FieldDiffs parse(@Nullable String s) {
114        FieldDiffs diffs = new FieldDiffs();
115        if (!Strings.isNullOrEmpty(s)) {
116          Iterable<String> fields = FIELDS_SPLITTER.split(s);
117          for (String field : fields) {
118            String[] keyValues = field.split("=");
119            if (keyValues.length == 2) {
120              String[] values = keyValues[1].split("\\|");
121              String oldValue = "";
122              String newValue = "";
123              if(values.length == 1) {
124                newValue = Strings.nullToEmpty(values[0]);
125              } else if(values.length == 2) {
126                oldValue = Strings.nullToEmpty(values[0]);
127                newValue = Strings.nullToEmpty(values[1]);
128              }
129              diffs.setDiff(keyValues[0], oldValue, newValue);
130            } else {
131              diffs.setDiff(keyValues[0], "", "");
132            }
133          }
134        }
135        return diffs;
136      }
137    
138      public static class Diff<T extends Serializable> implements Serializable {
139        private T oldValue, newValue;
140    
141        public Diff(@Nullable T oldValue, @Nullable T newValue) {
142          this.oldValue = oldValue;
143          this.newValue = newValue;
144        }
145    
146        @CheckForNull
147        public T oldValue() {
148          return oldValue;
149        }
150    
151        @CheckForNull
152        public Long oldValueLong() {
153          return toLong(oldValue);
154        }
155    
156        @CheckForNull
157        public T newValue() {
158          return newValue;
159        }
160    
161        @CheckForNull
162        public Long newValueLong() {
163          return toLong(newValue);
164        }
165    
166        void setNewValue(T t) {
167          this.newValue = t;
168        }
169    
170        @CheckForNull
171        private Long toLong(Serializable value) {
172          if (value != null && !"".equals(value)) {
173            try {
174              return Long.valueOf((String) value);
175            } catch (ClassCastException e) {
176              return (Long) value;
177            }
178          }
179          return null;
180        }
181    
182        @Override
183        public String toString() {
184          //TODO escape , and | characters
185          StringBuilder sb = new StringBuilder();
186          if(newValue != null) {
187            if(oldValue != null) {
188              sb.append(oldValue.toString());
189              sb.append('|');
190            }
191            sb.append(newValue.toString());
192          }
193          return sb.toString();
194        }
195      }
196    }