1 16 package org.outerj.daisy.docdiff; 17 18 import org.outerj.daisy.repository.*; 19 import org.outerj.daisy.xmlutil.XmlEncodingDetector; 20 21 import java.util.Arrays ; 22 23 28 public class DiffGenerator { 29 private Version version1; 30 private Version version2; 31 private boolean hasRun = false; 32 private DocDiffOutput output; 33 private static final long DIFF_LIMIT = 500000; 35 public DiffGenerator(Version version1, Version version2, DocDiffOutput output) { 36 this.version1 = version1; 37 this.version2 = version2; 38 this.output = output; 39 } 40 41 public void generateDiff() throws Exception { 42 if (hasRun) 43 throw new Exception ("DiffGenerator object can only be used once"); 44 hasRun = true; 45 46 output.begin(); 47 48 generatePartDifferences(); 49 generateFieldDifferences(); 50 generateLinkDifferences(); 51 52 output.end(); 53 54 version1 = null; 55 version2 = null; 56 output = null; 57 } 58 59 private void generatePartDifferences() throws Exception { 60 output.beginPartChanges(); 61 62 Part[] version1Parts = version1.getPartsInOrder().getArray(); 63 Part[] version2Parts = version2.getPartsInOrder().getArray(); 64 65 for (int i = 0; i < version1Parts.length; i++) { 67 long typeId = version1Parts[i].getTypeId(); 68 if (findPart(version2Parts, typeId) == null) { 69 output.partRemoved(version1Parts[i]); 70 } 71 } 72 73 for (int i = 0; i < version2Parts.length; i++) { 75 Part version2Part = version2Parts[i]; 76 Part version1Part = findPart(version1Parts, version2Part.getTypeId()); 77 if (version1Part == null) { 78 output.partAdded(version2Part); 79 } else { 80 if (version1Part.getSize() > DIFF_LIMIT || version2Part.getSize() > DIFF_LIMIT) { 81 output.partMightBeUpdated(version2Part); 82 } else { 83 String version1MimeType = version1Part.getMimeType(); 84 String version2MimeType = version2Part.getMimeType(); 85 86 String version1FileName = version1Part.getFileName(); 87 String version2FileName = version2Part.getFileName(); 88 89 boolean mimeTypesEqual = version1MimeType.equals(version2MimeType); 90 boolean fileNamesEqual = (version1FileName == null && version2FileName == null) || (version1FileName != null && version1FileName.equals(version2FileName)); 91 boolean dataEqual; 92 93 byte[] version1Data = null; 94 byte[] version2Data = null; 95 96 if (version1Part.getSize() != version2Part.getSize()) { 97 dataEqual = false; 98 } else { 99 version1Data = version1Part.getData(); 100 version2Data = version2Part.getData(); 101 dataEqual = Arrays.equals(version1Data, version2Data); 102 } 103 104 if (mimeTypesEqual && fileNamesEqual && dataEqual) { 105 output.partUnchanged(version2Part); 107 } else { 108 String part1String = null, part2String = null; 109 if (!dataEqual && version1MimeType.startsWith("text/") && version2MimeType.startsWith("text/")) { 110 if (version1Data == null) { 112 version1Data = version1Part.getData(); 113 version2Data = version2Part.getData(); 114 } 115 116 if (version1MimeType.equals("text/xml")) 119 part1String = new String (version1Data, XmlEncodingDetector.detectEncoding(version1Data)); 120 else 121 part1String = new String (version1Data); 122 123 if (version1MimeType.equals("text/xml")) 124 part2String = new String (version2Data, XmlEncodingDetector.detectEncoding(version2Data)); 125 else 126 part2String = new String (version2Data); 127 } 128 129 output.partUpdated(version1Part, version2Part, part1String, part2String); 130 131 version1Data = null; 132 version2Data = null; 133 } 134 } 135 } 136 } 137 138 output.endPartChanges(); 139 } 140 141 private void generateFieldDifferences() throws Exception { 142 output.beginFieldChanges(); 143 144 Field[] version1Fields = version1.getFields().getArray(); 145 Field[] version2Fields = version2.getFields().getArray(); 146 147 for (int i = 0; i < version1Fields.length; i++) { 149 long typeId = version1Fields[i].getTypeId(); 150 if (findField(version2Fields, typeId) == null) { 151 output.fieldRemoved(version1Fields[i]); 152 } 153 } 154 155 for (int i = 0; i < version2Fields.length; i++) { 157 Field version2Field = version2Fields[i]; 158 Field version1Field = findField(version1Fields, version2Field.getTypeId()); 159 if (version1Field == null) { 160 output.fieldAdded(version2Field); 161 } else { 162 boolean updated = (version1Field.isMultiValue() && !Arrays.equals((Object [])version1Field.getValue(), (Object [])version2Field.getValue())) 163 || (!version1Field.isMultiValue() && !version1Field.getValue().equals(version2Field.getValue())); 164 if (updated) { 165 output.fieldUpdated(version1Field, version2Field); 166 } else { 167 } 169 } 170 } 171 172 output.endFieldChanges(); 173 } 174 175 private void generateLinkDifferences() throws Exception { 176 output.beginLinkChanges(); 177 178 Link[] version1Links = version1.getLinks().getArray(); 179 Link[] version2Links = version2.getLinks().getArray(); 180 181 for (int i = 0; i < version1Links.length; i++) { 183 if (findLink(version2Links, version1Links[i]) == null) { 184 output.linkRemoved(version1Links[i]); 185 } 186 } 187 188 for (int i = 0; i < version2Links.length; i++) { 190 Link version2Link = version2Links[i]; 191 Link version1Link = findLink(version1Links, version2Link); 192 if (version1Link == null) { 193 output.linkAdded(version2Link); 194 } else { 195 } 197 } 198 199 output.endLinkChanges(); 200 } 201 202 private Part findPart(Part[] parts, long typeId) { 203 for (int k = 0; k < parts.length; k++) { 204 if (parts[k].getTypeId() == typeId) { 205 return parts[k]; 206 } 207 } 208 return null; 209 } 210 211 private Field findField(Field[] fields, long typeId) { 212 for (int k = 0; k < fields.length; k++) { 213 if (fields[k].getTypeId() == typeId) { 214 return fields[k]; 215 } 216 } 217 return null; 218 } 219 220 private Link findLink(Link[] links, Link link) { 221 for (int k = 0; k < links.length; k++) { 222 if (links[k].getTitle().equals(link.getTitle()) && links[k].getTarget().equals(link.getTarget())) { 223 return links[k]; 224 } 225 } 226 return null; 227 } 228 229 } 230 | Popular Tags |