001: package org.enhydra.shark.xpdl;
002:
003: import java.util.ArrayList;
004: import java.util.Iterator;
005: import java.util.List;
006:
007: import org.enhydra.shark.utilities.SequencedHashMap;
008:
009: /**
010: * Class that represents collection of elements from XML schema.
011: *
012: * @author Sasa Bojanic
013: */
014: public abstract class XMLCollection extends
015: XMLBaseForCollectionAndComplex {
016:
017: public XMLCollection(XMLComplexElement parent, boolean isRequired) {
018: super (parent, isRequired);
019: }
020:
021: public XMLCollection(XMLComplexElement parent, String name,
022: boolean isRequired) {
023: super (parent, name, isRequired);
024: }
025:
026: public XMLCollection(XMLComplexChoice parent, boolean isRequired) {
027: super (parent, isRequired);
028: }
029:
030: public XMLCollection(XMLComplexChoice parent, String name,
031: boolean isRequired) {
032: super (parent, name, isRequired);
033: }
034:
035: public XMLCollection(XMLCollection parent, boolean isRequired) {
036: super (parent, isRequired);
037: }
038:
039: public XMLCollection(XMLCollection parent, String name,
040: boolean isRequired) {
041: super (parent, name, isRequired);
042: }
043:
044: public void makeAs(XMLElement el) {
045: if (!(el != null && el.getClass().equals(this .getClass()) && el
046: .toName().equals(this .toName()))) {
047: throw new RuntimeException("Can't perform makeAs!");
048: }
049: //System.err.println("Performing make as for element "+el.toName()+", pkg="+getMainElement().hashCode()+", mapkg="+el.getMainElement().hashCode()+", notifml="+notifyMainListeners);
050: SequencedHashMap oldElsMap = new SequencedHashMap();
051: SequencedHashMap newElsMap = new SequencedHashMap();
052: Iterator it = toElements().iterator();
053: while (it.hasNext()) {
054: XMLElement o = (XMLElement) it.next();
055: oldElsMap.put(o.getOriginalElementHashCode(), o);
056: }
057: //System.err.println("OLDELSMAP="+oldElsMap);
058: it = ((XMLCollection) el).toElements().iterator();
059: while (it.hasNext()) {
060: XMLElement o = (XMLElement) it.next();
061: if (!oldElsMap.containsKey(o.getOriginalElementHashCode())) {
062: XMLElement temp = generateNewElement();
063: // XMLElement temp = (XMLElement)o.clone();
064: temp.makeAs(o);
065: newElsMap.put(temp.getOriginalElementHashCode(), temp);
066: } else {
067: newElsMap.put(o.getOriginalElementHashCode(), o);
068: }
069: }
070: //if (this instanceof ExtendedAttributes) System.err.println("NEWSMAP="+oldElsMap);
071:
072: List toAdd = new ArrayList(newElsMap.keySet());
073: toAdd.removeAll(oldElsMap.keySet());
074: //System.err.println("TOADD="+toAdd);
075: List toRemove = new ArrayList(oldElsMap.keySet());
076: toRemove.removeAll(newElsMap.keySet());
077: //System.err.println("TOREM="+toRemove);
078: List toRetain = new ArrayList(oldElsMap.keySet());
079: toRetain.retainAll(newElsMap.keySet());
080: //System.err.println("TORET="+toRetain);
081: List objectsToRemove = new ArrayList();
082: it = toRemove.iterator();
083: while (it.hasNext()) {
084: XMLElement elToRemove = (XMLElement) oldElsMap.get(it
085: .next());
086: objectsToRemove.add(elToRemove);
087: }
088: List objectsToAdd = new ArrayList();
089: it = toAdd.iterator();
090: while (it.hasNext()) {
091: objectsToAdd.add(newElsMap.get(it.next()));
092: }
093:
094: it = toRetain.iterator();
095: while (it.hasNext()) {
096: Object next = it.next();
097: XMLElement oldEl = (XMLElement) oldElsMap.get(next);
098: XMLElement newEl = (XMLElement) newElsMap.get(next);
099: oldEl.makeAs(newEl);
100: }
101:
102: removeAll(objectsToRemove);
103: addAll(objectsToAdd);
104:
105: oldElsMap.clear();
106: it = toElements().iterator();
107: while (it.hasNext()) {
108: XMLElement o = (XMLElement) it.next();
109: oldElsMap.put(o.getOriginalElementHashCode(), o);
110: }
111: checkRepositioning(oldElsMap, newElsMap);
112:
113: }
114:
115: public void initCaches() {
116: super .initCaches();
117: if (elements.size() > 0
118: && elements.get(0) instanceof XMLCollectionElement) {
119: elementMap.clear();
120: Iterator it = elements.iterator();
121: while (it.hasNext()) {
122: XMLCollectionElement el = (XMLCollectionElement) it
123: .next();
124: elementMap.put(el.getId(), el);
125: }
126: }
127: cachesInitialized = true;
128: }
129:
130: public void clearCaches() {
131: super .clearCaches();
132: elementMap.clear();
133: }
134:
135: /** NOTE: Method signature changed to public. */
136: public void add(XMLElement el) {
137: if (isReadOnly) {
138: throw new RuntimeException(
139: "Can't set the value of read only element!");
140: }
141: List changedSubElements = new ArrayList();
142: changedSubElements.add(el);
143:
144: elements.add(el);
145: el.setParent(this );
146: // el.originalElementHashCode=null;
147: el.setNotifyListeners(this .notifyListeners);
148: el.setNotifyMainListeners(this .notifyMainListeners);
149:
150: XMLElementChangeInfo info = createInfo(value, value,
151: changedSubElements, XMLElementChangeInfo.INSERTED);
152: if (notifyListeners) {
153: notifyListeners(info);
154: }
155: if (notifyMainListeners) {
156: notifyMainListeners(info);
157: }
158: }
159:
160: /** NOTE: Method signature changed to public. */
161: public boolean add(int no, XMLElement el) {
162: if (isReadOnly) {
163: throw new RuntimeException(
164: "Can't set the value of read only element!");
165: }
166: if (no < 0 || no > size())
167: throw new RuntimeException("Can't add element to position "
168: + no + "!");
169: List changedSubElements = new ArrayList();
170: changedSubElements.add(el);
171:
172: elements.add(el);
173: el.setParent(this );
174: // el.originalElementHashCode=null;
175: el.setNotifyListeners(this .notifyListeners);
176: el.setNotifyMainListeners(this .notifyMainListeners);
177:
178: XMLElementChangeInfo info = createInfo(value, value,
179: changedSubElements, XMLElementChangeInfo.INSERTED);
180: if (notifyListeners) {
181: notifyListeners(info);
182: }
183: if (notifyMainListeners) {
184: notifyMainListeners(info);
185: }
186:
187: reposition(el, no);
188:
189: return true;
190: }
191:
192: public boolean addAll(List els) {
193: if (isReadOnly) {
194: throw new RuntimeException(
195: "Can't set the value of read only element!");
196: }
197: if (els != null && els.size() > 0) {
198: Iterator it = els.iterator();
199: while (it.hasNext()) {
200: XMLElement el = (XMLElement) it.next();
201: elements.add(el);
202: el.setParent(this );
203: // el.originalElementHashCode=null;
204: el.setNotifyListeners(this .notifyListeners);
205: el.setNotifyMainListeners(this .notifyMainListeners);
206: }
207: List changedSubElements = new ArrayList(els);
208: XMLElementChangeInfo info = createInfo(value, value,
209: changedSubElements, XMLElementChangeInfo.INSERTED);
210: if (notifyListeners) {
211: notifyListeners(info);
212: }
213: if (notifyMainListeners) {
214: notifyMainListeners(info);
215: }
216: return true;
217: }
218:
219: return false;
220: }
221:
222: public int remove(XMLElement el) {
223: if (isReadOnly) {
224: throw new RuntimeException(
225: "Can't remove element from read only structure!");
226: }
227: int ind = indexOf(el);
228: if (ind >= 0) {
229: removeElement(ind);
230: }
231: return ind;
232: }
233:
234: public XMLElement remove(int no) {
235: if (isReadOnly) {
236: throw new RuntimeException(
237: "Can't remove element from read only structure!");
238: }
239: if (no < 0 || no >= size())
240: throw new RuntimeException(
241: "There is no element at position " + no + "!");
242:
243: return removeElement(no);
244: }
245:
246: protected XMLElement removeElement(int no) {
247: XMLElement el = (XMLElement) elements.remove(no);
248:
249: if (el != null) {
250: List oldPositions = new ArrayList();
251: oldPositions.add(new Integer(no));
252: List newPositions = new ArrayList();
253: newPositions.add(new Integer(no));
254: List changedPosition = new ArrayList();
255: changedPosition.add(el);
256:
257: if (changedPosition.size() > 0) {
258: XMLElementChangeInfo info = createInfo(oldPositions,
259: newPositions, changedPosition,
260: XMLElementChangeInfo.REPOSITIONED);
261: if (notifyListeners) {
262: notifyListeners(info);
263: }
264: if (notifyMainListeners) {
265: notifyMainListeners(info);
266: }
267: }
268:
269: el.setNotifyListeners(false);
270: el.setNotifyMainListeners(false);
271: List changedSubElements = new ArrayList();
272: changedSubElements.add(el);
273:
274: elementMap.remove(el);
275:
276: XMLElementChangeInfo info = createInfo(value, value,
277: changedSubElements, XMLElementChangeInfo.REMOVED);
278: if (notifyListeners) {
279: notifyListeners(info);
280: }
281: if (notifyMainListeners) {
282: notifyMainListeners(info);
283: }
284: }
285:
286: return el;
287: }
288:
289: public boolean removeAll(List els) {
290: if (isReadOnly) {
291: throw new RuntimeException(
292: "Can't remove element from read only structure!");
293: }
294: if (els != null && els.size() > 0) {
295: List changedSubElements = new ArrayList(els);
296:
297: List oldPositions = new ArrayList();
298: List newPositions = new ArrayList();
299:
300: Iterator it = els.iterator();
301: while (it.hasNext()) {
302: XMLElement el = (XMLElement) it.next();
303: int oldPos = indexOf(el);
304: if (oldPos < 0) {
305: XMLUtil.removeXMLElementFromList(
306: changedSubElements, el);
307: } else {
308: oldPositions.add(new Integer(oldPos));
309: newPositions.add(new Integer(oldPos));
310: }
311: }
312:
313: if (changedSubElements.size() > 0) {
314: XMLElementChangeInfo info = createInfo(oldPositions,
315: newPositions, changedSubElements,
316: XMLElementChangeInfo.REPOSITIONED);
317: if (notifyListeners) {
318: notifyListeners(info);
319: }
320: if (notifyMainListeners) {
321: notifyMainListeners(info);
322: }
323: }
324:
325: it = changedSubElements.iterator();
326: while (it.hasNext()) {
327: XMLElement el = (XMLElement) it.next();
328: el.setNotifyListeners(false);
329: el.setNotifyMainListeners(false);
330: elements.remove(indexOf(el));
331: elementMap.remove(el);
332: }
333:
334: XMLElementChangeInfo info = createInfo(value, value,
335: changedSubElements, XMLElementChangeInfo.REMOVED);
336: if (notifyListeners) {
337: notifyListeners(info);
338: }
339: if (notifyMainListeners) {
340: notifyMainListeners(info);
341: }
342: return true;
343: }
344:
345: return false;
346: }
347:
348: public boolean reposition(XMLElement el, int newPos) {
349: if (isReadOnly) {
350: throw new RuntimeException(
351: "Can't reposition element from read only structure!");
352: }
353: int oldPos = indexOf(el);
354: if (newPos < 0 || newPos > size() || oldPos < 0
355: || oldPos == newPos)
356: return false;
357:
358: List oldPositions = new ArrayList();
359: oldPositions.add(new Integer(indexOf(el)));
360: List newPositions = new ArrayList();
361: newPositions.add(new Integer(newPos));
362: List changedPosition = new ArrayList();
363: changedPosition.add(el);
364:
365: elements.remove(((Integer) oldPositions.get(0)).intValue());
366: elements.add(newPos, el);
367:
368: if (changedPosition.size() > 0) {
369: XMLElementChangeInfo info = createInfo(oldPositions,
370: newPositions, changedPosition,
371: XMLElementChangeInfo.REPOSITIONED);
372: if (notifyListeners) {
373: notifyListeners(info);
374: }
375: if (notifyMainListeners) {
376: notifyMainListeners(info);
377: }
378: }
379:
380: return true;
381: }
382:
383: /**
384: * Returns <tt>true</tt> if there are no elements within collection.
385: */
386: public boolean isEmpty() {
387: return size() == 0;
388: }
389:
390: /**
391: * Returns the element specified by Id attribute.
392: * Use only if this is collection of XMLCollectionElements.
393: */
394: public XMLCollectionElement getCollectionElement(String id) {
395: if (isReadOnly && cachesInitialized) {
396: return (XMLCollectionElement) elementMap.get(id);
397: }
398:
399: Iterator it = elements.iterator();
400: while (it.hasNext()) {
401: XMLCollectionElement ce = (XMLCollectionElement) it.next();
402: if (ce.getId().equals(id)) {
403: return ce;
404: }
405: }
406: return null;
407: }
408:
409: /**
410: * Returns true if element with given Id exists in collection.
411: */
412: public boolean containsElement(String id) {
413: return getCollectionElement(id) != null;
414: }
415:
416: public int indexOf(XMLElement el) {
417: return XMLUtil.indexOfXMLElementWithinList(elements, el);
418: }
419:
420: /** Clears the collection. */
421: public void clear() {
422: int size = elements.size();
423:
424: List changedSubElements = new ArrayList(elements);
425:
426: Iterator it = elements.iterator();
427: while (it.hasNext()) {
428: XMLElement el = (XMLElement) it.next();
429: el.setNotifyListeners(false);
430: el.setNotifyMainListeners(false);
431: }
432: elements.clear();
433: elementMap.clear();
434:
435: if (size > 0) {
436: XMLElementChangeInfo info = createInfo(value, value,
437: changedSubElements, XMLElementChangeInfo.REMOVED);
438: if (notifyListeners) {
439: notifyListeners(info);
440: }
441: if (notifyMainListeners) {
442: notifyMainListeners(info);
443: }
444: }
445: }
446:
447: /**
448: * Generates the new element that made collection. Derived classes
449: * has to implement this method to create it's collection element.
450: */
451: public abstract XMLElement generateNewElement();
452:
453: protected void checkRepositioning(SequencedHashMap oldEls,
454: SequencedHashMap newEls) {
455: // System.err.println("CHECKREPFOR "+this);
456: List oldPositions = new ArrayList();
457: List newPositions = new ArrayList();
458: List changedPosition = new ArrayList();
459: List toReposition = new ArrayList(newEls.sequence());
460: // toRetain.retainAll(newEls.keySet());
461:
462: //System.err.println("Start Repositioning, oldEls= "+oldEls+", newEls="+newEls);
463:
464: for (int i = 0; i < toReposition.size(); i++) {
465: int oldpos = oldEls.indexOf(toReposition.get(i));
466: // System.err.println("OLDPOS="+oldpos);
467: int newpos = newEls.indexOf(toReposition.get(i));
468: // System.err.println("NEWPOS="+newpos);
469: if (oldpos != newpos) {
470: Object e = elements.get(oldpos);
471: changedPosition.add(e);
472: oldPositions.add(new Integer(oldpos));
473: newPositions.add(new Integer(newpos));
474: }
475: }
476:
477: if (changedPosition.size() > 0) {
478: for (int i = 0; i < changedPosition.size(); i++) {
479: XMLElement e = (XMLElement) changedPosition.get(i);
480: elements.remove(indexOf(e));
481: elements.add(
482: ((Integer) newPositions.get(i)).intValue(), e);
483: }
484:
485: XMLElementChangeInfo info = createInfo(oldPositions,
486: newPositions, changedPosition,
487: XMLElementChangeInfo.REPOSITIONED);
488: if (notifyListeners) {
489: notifyListeners(info);
490: }
491: if (notifyMainListeners) {
492: notifyMainListeners(info);
493: }
494: }
495: }
496:
497: public Object clone() {
498: XMLCollection d = (XMLCollection) super .clone();
499: d.elements = new ArrayList();
500: d.elementMap = new SequencedHashMap();
501: d.cachesInitialized = false;
502: Iterator it = this .elements.iterator();
503: while (it.hasNext()) {
504: Object obj = it.next();
505: XMLElement el = (XMLElement) obj;
506: XMLElement cl = (XMLElement) el.clone();
507: cl.setParent(d);
508: d.elements.add(cl);
509: }
510: return d;
511: }
512:
513: }
|