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 */ 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 createdAt, updatedAt; 045 private final Map<String, Diff> diffs = Maps.newLinkedHashMap(); 046 047 public Map<String, Diff> diffs() { 048 return diffs; 049 } 050 051 public Diff get(String field) { 052 return diffs.get(field); 053 } 054 055 @CheckForNull 056 public String userLogin() { 057 return userLogin; 058 } 059 060 public FieldDiffs setUserLogin(@Nullable String s) { 061 this.userLogin = s; 062 return this; 063 } 064 065 public Date createdAt() { 066 return createdAt; 067 } 068 069 public FieldDiffs setCreatedAt(Date d) { 070 this.createdAt = d; 071 return this; 072 } 073 074 public Date updatedAt() { 075 return updatedAt; 076 } 077 078 public FieldDiffs setUpdatedAt(Date d) { 079 this.updatedAt = d; 080 return this; 081 } 082 083 public String issueKey() { 084 return issueKey; 085 } 086 087 public FieldDiffs setIssueKey(String issueKey) { 088 this.issueKey = issueKey; 089 return this; 090 } 091 092 @SuppressWarnings("unchecked") 093 public FieldDiffs setDiff(String field, @Nullable Serializable oldValue, @Nullable Serializable newValue) { 094 Diff diff = diffs.get(field); 095 if (diff == null) { 096 diff = new Diff(oldValue, newValue); 097 diffs.put(field, diff); 098 } else { 099 diff.setNewValue(newValue); 100 } 101 return this; 102 } 103 104 @Override 105 public String toString() { 106 StringBuilder sb = new StringBuilder(); 107 boolean notFirst = false; 108 for (Map.Entry<String, Diff> entry : diffs.entrySet()) { 109 if (notFirst) { 110 sb.append(','); 111 } else { 112 notFirst = true; 113 } 114 sb.append(entry.getKey()); 115 sb.append('='); 116 sb.append(entry.getValue().toString()); 117 } 118 return sb.toString(); 119 } 120 121 public static FieldDiffs parse(@Nullable String s) { 122 FieldDiffs diffs = new FieldDiffs(); 123 if (!Strings.isNullOrEmpty(s)) { 124 Iterable<String> fields = FIELDS_SPLITTER.split(s); 125 for (String field : fields) { 126 String[] keyValues = field.split("="); 127 if (keyValues.length == 2) { 128 String[] values = keyValues[1].split("\\|"); 129 String oldValue = ""; 130 String newValue = ""; 131 if(values.length == 1) { 132 newValue = Strings.nullToEmpty(values[0]); 133 } else if(values.length == 2) { 134 oldValue = Strings.nullToEmpty(values[0]); 135 newValue = Strings.nullToEmpty(values[1]); 136 } 137 diffs.setDiff(keyValues[0], oldValue, newValue); 138 } else { 139 diffs.setDiff(keyValues[0], "", ""); 140 } 141 } 142 } 143 return diffs; 144 } 145 146 public static class Diff<T extends Serializable> implements Serializable { 147 private T oldValue, newValue; 148 149 public Diff(@Nullable T oldValue, @Nullable T newValue) { 150 this.oldValue = oldValue; 151 this.newValue = newValue; 152 } 153 154 @CheckForNull 155 public T oldValue() { 156 return oldValue; 157 } 158 159 @CheckForNull 160 public Long oldValueLong() { 161 return toLong(oldValue); 162 } 163 164 @CheckForNull 165 public T newValue() { 166 return newValue; 167 } 168 169 @CheckForNull 170 public Long newValueLong() { 171 return toLong(newValue); 172 } 173 174 void setNewValue(T t) { 175 this.newValue = t; 176 } 177 178 @CheckForNull 179 private Long toLong(Serializable value) { 180 if (value != null && !"".equals(value)) { 181 try { 182 return Long.valueOf((String) value); 183 } catch (ClassCastException e) { 184 return (Long) value; 185 } 186 } 187 return null; 188 } 189 190 @Override 191 public String toString() { 192 //TODO escape , and | characters 193 StringBuilder sb = new StringBuilder(); 194 if(newValue != null) { 195 if(oldValue != null) { 196 sb.append(oldValue.toString()); 197 sb.append('|'); 198 } 199 sb.append(newValue.toString()); 200 } 201 return sb.toString(); 202 } 203 } 204 }