1 package net.sf.jpkgmk.pkgmap;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.Writer;
6 import java.util.ArrayList;
7 import java.util.Collections;
8 import java.util.Comparator;
9 import java.util.HashSet;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.ListIterator;
13 import java.util.Set;
14
15 import net.sf.jpkgmk.AbstractFileCreatorAdapter;
16 import net.sf.jpkgmk.DefaultFileHandler;
17 import net.sf.jpkgmk.FileHandler;
18 import net.sf.jpkgmk.PackageException;
19 import net.sf.jpkgmk.util.ObjectUtils;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class PkgMap extends AbstractFileCreatorAdapter
45 {
46
47
48
49 private static final Integer ONE = Integer.valueOf(1);
50
51
52
53
54 public static final String PKGMAP="pkgmap";
55
56
57 private Log log = LogFactory.getLog(PkgMap.class);
58
59
60
61 private List<PkgMapEntry> pkgMapEntryList = new ArrayList<PkgMapEntry>();
62 private PkgMapEntryHeader header;
63
64
65
66 public PkgMap() {
67 super();
68 }
69
70
71
72 @Override
73 public FileHandler getFileHandler(File targetDir) {
74 DefaultFileHandler fileCreator = new DefaultFileHandler(targetDir, PKGMAP);
75 return fileCreator;
76 }
77
78
79 public void writeContent(Writer writer) throws IOException
80 {
81
82 if(this.header == null) {
83 throw new IllegalStateException("Before creating the pkgmap, the header must be set via setHeader().");
84 }
85 header.write(writer);
86
87
88 sort(this.pkgMapEntryList);
89
90
91 for(Iterator<PkgMapEntry> iter=this.pkgMapEntryList.iterator(); iter.hasNext(); ) {
92 PkgMapEntry entry = (PkgMapEntry)iter.next();
93 entry.write(writer);
94 }
95 writer.flush();
96 }
97
98
99
100
101
102
103
104
105
106
107 void sort(List<PkgMapEntry> pkgMapEntryList2) {
108
109 log.debug("<entering> sort(List<PkgMapEntry>)");
110
111 List<EntryCommentAssociation> entryCommandAssocList = createEntryCommandAssoc(pkgMapEntryList2);
112
113
114 List<PkgMapEntry> entryListWithoutComments = filterComments(pkgMapEntryList2);
115
116 Collections.sort(entryListWithoutComments, new PkgMapEntrySorter());
117
118 List<PkgMapEntry> fullResultList = addCommentsIfNeeded(entryListWithoutComments, entryCommandAssocList);
119
120 this.pkgMapEntryList = fullResultList;
121 }
122
123 private List<PkgMapEntry> addCommentsIfNeeded(List<PkgMapEntry> entryListWithoutComments,
124 List<EntryCommentAssociation> entryCommandAssocList) {
125
126 List<PkgMapEntry> resultList = new ArrayList<PkgMapEntry>();
127 for(PkgMapEntry currentEntry : entryListWithoutComments) {
128
129 for(EntryCommentAssociation entryCommentAssoc : entryCommandAssocList)
130 {
131 if(entryCommentAssoc.getEntry().equals(currentEntry)) {
132
133 resultList.addAll(entryCommentAssoc.getCommentList());
134 break;
135 }
136 }
137
138 resultList.add(currentEntry);
139 }
140 return resultList;
141 }
142
143
144 private List<PkgMapEntry> filterComments(List<PkgMapEntry> pkgMapEntryList2) {
145 List<PkgMapEntry> resultList = new ArrayList<PkgMapEntry>();
146 for (PkgMapEntry pkgMapEntry : pkgMapEntryList2) {
147 if( !(pkgMapEntry instanceof PkgMapEntryComment)) {
148 resultList.add(pkgMapEntry);
149 }
150 }
151 return resultList;
152 }
153
154
155 private List<EntryCommentAssociation> createEntryCommandAssoc(List<PkgMapEntry> pkgMapEntryList2) {
156 List<EntryCommentAssociation> assocList = new ArrayList<EntryCommentAssociation>();
157 List<PkgMapEntryComment> commentList = new ArrayList<PkgMapEntryComment>();
158
159 for(PkgMapEntry entry : pkgMapEntryList2) {
160 if(entry instanceof PkgMapEntryComment) {
161
162 commentList.add((PkgMapEntryComment)entry);
163 }
164 else {
165 AbstractPkgMapEntry mapEntry = (AbstractPkgMapEntry)entry;
166 if(!commentList.isEmpty()) {
167
168 EntryCommentAssociation entryCommentAssoc = new EntryCommentAssociation(mapEntry, commentList);
169 assocList.add(entryCommentAssoc);
170
171 commentList = new ArrayList<PkgMapEntryComment>();
172 }
173 else {
174 log.debug("Comment list is empty. No need to create a comment association for current entry.");
175 }
176 }
177 }
178 return assocList;
179 }
180
181
182
183
184
185
186 public List<PkgMapEntry> getPkgMapEntries()
187 {
188 return Collections.unmodifiableList(this.pkgMapEntryList);
189 }
190
191
192
193
194
195 public void addAll(List<PkgMapEntry> pkgMapEntryList) {
196 for (Iterator<PkgMapEntry> iterator = pkgMapEntryList.iterator(); iterator.hasNext();) {
197 PkgMapEntry pkgMapEntry = iterator.next();
198 this.add(pkgMapEntry);
199 }
200 }
201
202
203
204
205
206
207 public void add(PkgMapEntry entry) {
208 log.debug("Adding entry: " + entry);
209
210 if(PkgMapEntryHeader.class.isAssignableFrom(entry.getClass())) {
211 this.setHeader((PkgMapEntryHeader)entry);
212 }
213 else {
214 if(pkgMapEntryList.contains(entry)) {
215
216 PkgMapEntry existingEntry = findEntryThatEquals(entry);
217 throw new PackageException("Entry that equals the given one '" + entry + "' already exists in the current map. Equal entry in list: '" + existingEntry + "'.");
218 }
219 boolean success = pkgMapEntryList.add(entry);
220 if(!success) {
221 throw new PackageException("Failed to add the entry '" + entry + "' to the map.");
222
223 }
224 }
225 }
226
227
228
229
230
231 public void setHeader(PkgMapEntryHeader header) {
232 if(this.header != null) {
233 throw new IllegalStateException("The header is already set. Cannot overwrite");
234 }
235 if(header == null) {
236 log.info("Resetting pkgmap header to null");
237 }
238 this.header = header;
239 }
240
241 public PkgMapEntryHeader getHeader() {
242 return this.header;
243 }
244
245
246
247
248 public int getSize() {
249 return this.pkgMapEntryList.size();
250 }
251
252
253
254
255
256
257 private PkgMapEntry findEntryThatEquals(PkgMapEntry entry)
258 {
259 for(Iterator<PkgMapEntry> iter=this.pkgMapEntryList.iterator(); iter.hasNext(); ) {
260 PkgMapEntry currentEntry = (PkgMapEntry)iter.next();
261 if(currentEntry.equals(entry)) {
262 return currentEntry;
263 }
264 }
265 return null;
266 }
267
268
269
270
271
272 public Integer getNumberOfParts() {
273 Set<Integer> foundParts = new HashSet<Integer>();
274 for(Iterator<PkgMapEntry> iter=this.pkgMapEntryList.iterator(); iter.hasNext(); ) {
275 PkgMapEntry currentEntry = (PkgMapEntry)iter.next();
276 if(PkgMapEntryFile.class.isAssignableFrom(currentEntry.getClass())) {
277 PkgMapEntryFile currentEntryFile = (PkgMapEntryFile)currentEntry;
278 Integer part = currentEntryFile.getPart();
279 if(part==null) {
280
281 part = ONE;
282 }
283 foundParts.add(part);
284 }
285 }
286 return foundParts.size();
287 }
288
289 @Override
290 public int hashCode() {
291 final int prime = 31;
292 int result = 1;
293 result = prime * result + ((header == null) ? 0 : header.hashCode());
294 result = prime * result
295 + ((pkgMapEntryList == null) ? 0 : pkgMapEntryList.hashCode());
296 return result;
297 }
298
299
300
301 @Override
302 public boolean equals(Object obj) {
303 return this.equals(obj, false);
304 }
305
306
307
308
309
310
311 public boolean equals(Object obj, boolean ignoreLastModified) {
312 if (this == obj)
313 return true;
314 if (obj == null)
315 return false;
316 if (getClass() != obj.getClass())
317 return false;
318 final PkgMap other = (PkgMap) obj;
319
320 if(!ObjectUtils.areObjectsEqual(this.header, other.header))
321 return false;
322
323 if (pkgMapEntryList == null) {
324 if (other.pkgMapEntryList != null)
325 return false;
326 } else if (!listsEqual(pkgMapEntryList, other.pkgMapEntryList, ignoreLastModified))
327 return false;
328 return true;
329 }
330
331
332
333 private boolean listsEqual(List<PkgMapEntry> list1,
334 List<PkgMapEntry> list2, boolean ignoreLastModified) {
335 if(!ignoreLastModified) {
336 return list1.equals(list2);
337 }
338 else {
339
340 ListIterator<PkgMapEntry> e1 = list1.listIterator();
341 ListIterator<PkgMapEntry> e2 = list2.listIterator();
342 while(e1.hasNext() && e2.hasNext()) {
343 PkgMapEntry o1 = e1.next();
344 PkgMapEntry o2 = e2.next();
345 if (!(o1==null ? o2==null : o1.equals(o2, ignoreLastModified)))
346 return false;
347 }
348 return !(e1.hasNext() || e2.hasNext());
349 }
350 }
351
352
353
354 @Override
355 public String toString()
356 {
357 StringBuffer sb = new StringBuffer();
358 sb.append(getClass().getName()).append("[");
359 sb.append(super.toString());
360 sb.append("[");
361 sb.append("entries=").append(this.pkgMapEntryList);
362 sb.append("]");
363 sb.append("]");
364 return sb.toString();
365 }
366
367
368
369
370
371
372
373 private static class PkgMapEntrySorter implements Comparator<PkgMapEntry>
374 {
375
376 public int compare(PkgMapEntry o1, PkgMapEntry o2) {
377 if(o1 instanceof PkgMapEntryHeader) {
378 return -1;
379 }
380 else if(o2 instanceof PkgMapEntryHeader) {
381 return 1;
382 }
383 else if(o1 instanceof AbstractPkgMapEntry && o2 instanceof AbstractPkgMapEntry) {
384 AbstractPkgMapEntry o1Abstract = (AbstractPkgMapEntry)o1;
385 AbstractPkgMapEntry o2Abstract = (AbstractPkgMapEntry)o2;
386 return o1Abstract.compareTo(o2Abstract);
387 }
388 else {
389 throw new UnsupportedOperationException("Unknown pkgmap entry type: " + o1 + " and " + o2);
390 }
391 }
392
393 }
394
395
396
397
398 private static class EntryCommentAssociation
399 {
400 private PkgMapEntry entry;
401 private List<PkgMapEntryComment> commentList;
402
403 public EntryCommentAssociation(PkgMapEntry entry, List<PkgMapEntryComment> commentList)
404 {
405 this.entry = entry;
406 this.commentList = commentList;
407 }
408
409 public PkgMapEntry getEntry() {
410 return entry;
411 }
412
413 public List<PkgMapEntryComment> getCommentList() {
414 return commentList;
415 }
416
417 }
418
419 }