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 }