001: /**
002: * Objective Database Abstraction Layer (ODAL)
003: * Copyright (c) 2004, The ODAL Development Group
004: * All rights reserved.
005: * For definition of the ODAL Development Group please refer to LICENCE.txt file
006: *
007: * Distributable under LGPL license.
008: * See terms of license at gnu.org.
009: */package com.completex.objective.components.persistency;
010:
011: import com.completex.objective.components.persistency.core.impl.LinkIterator;
012: import com.completex.objective.components.persistency.type.TracingCollection;
013: import com.completex.objective.util.PropertyMap;
014:
015: import java.io.Serializable;
016: import java.util.ArrayList;
017: import java.util.Iterator;
018: import java.util.LinkedHashMap;
019: import java.util.List;
020: import java.util.Map;
021:
022: /**
023: * Basic implemenatation of <code>Parent<code/>
024: *
025: * @author Gennady Krizhevsky
026: */
027: public abstract class ParentBase implements Parent, Serializable {
028: public static final String ROOT = "ROOT";
029: private LinkedHashMap children;
030: private transient Link parentLink;
031: private static final String TAG_CHILDREN = "children";
032:
033: /**
034: *
035: * @param children
036: */
037: public void setChildren(LinkedHashMap children) {
038: this .children = children;
039: }
040:
041: /**
042: *
043: * @return children Map<name, link>
044: */
045: public LinkedHashMap getChildren() {
046: return children;
047: }
048:
049: public void clearNonInlinedChildren() {
050: if (children != null) {
051: LinkedHashMap clonedMap = (LinkedHashMap) children.clone();
052: for (Iterator it = clonedMap.keySet().iterator(); it
053: .hasNext();) {
054: Object key = it.next();
055: Link child = (Link) children.get(key);
056: if (child == null || !child.isInline()) {
057: children.remove(key);
058: }
059: }
060: }
061: }
062:
063: /**
064: *
065: * @param link
066: * @throws NullPointerException if link has no name set
067: */
068: public void addChild(Link link) {
069: String name = link.getName();
070: if (name == null) {
071: throw new NullPointerException(
072: "Cannot add Link will null name");
073: }
074: lazyChildrenInitialization();
075:
076: if (ROOT.equals(name) /*|| children.containsKey(name)*/) {
077: throw new IllegalArgumentException("Child name [" + name
078: + "] already exists");
079: }
080: Link prevLink = (Link) children.get(name);
081: if (prevLink != null && link.getResult() == null) {
082: link.setResult(prevLink.getResult());
083: }
084: children.put(name, link);
085: link.setParentLink(toLink());
086: if (toLink() != null) {
087: link.addParentPath(toLink().getPath());
088: }
089: link.addToPath(name);
090: }
091:
092: /**
093: *
094: * @param name
095: * @param link
096: */
097: protected void addChild(String name, Link link) {
098: lazyChildrenInitialization();
099: if (ROOT.equals(name) /*|| children.containsKey(name)*/) {
100: throw new IllegalArgumentException("Child name [" + name
101: + "] already exists");
102: }
103: Link prevLink = (Link) children.get(name);
104: if (prevLink != null && link.getResult() == null) {
105: link.setResult(prevLink.getResult());
106: }
107: children.put(name, link);
108: link.setParentLink(toLink());
109: if (toLink() != null) {
110: link.addParentPath(toLink().getPath());
111: }
112: link.addToPath(name);
113: }
114:
115: /**
116: * Returns link representation of this object
117: *
118: * @return Link
119: */
120: public abstract Link toLink();
121:
122: /**
123: *
124: * @return Parent Link
125: */
126: public Link getParentLink() {
127: return parentLink;
128: }
129:
130: /**
131: *
132: * @param parentLink
133: */
134: public void setParentLink(Link parentLink) {
135: this .parentLink = parentLink;
136: }
137:
138: /**
139: *
140: * Get link by name and return its result
141: *
142: * @param name
143: * @return ChildObject
144: */
145: public Object getChildObject(String name) {
146: Object result = null;
147: Link link;
148: if (hasChildren()) {
149: link = getChild(name);
150: } else {
151: return null;
152: }
153: if (link.getResult() != null) {
154: result = link.getResult();
155: }
156: return result;
157: }
158:
159: /**
160: * Get link by name and set its result
161: *
162: * @param name
163: * @param value
164: */
165: public void setChildObject(String name, Object value) {
166: if (hasChildren()) {
167: Link link = getChild(name);
168: invalidateNull(link, name);
169: //
170: // If null was set for tracing collection containing one element
171: //
172: if (link.isTreatNullAsRemove() && link.getResult() != null
173: && link.getResult() instanceof TracingCollection) {
174: TracingCollection tracingCollection = (TracingCollection) link
175: .getResult();
176: tracingCollection.removeAll();
177: } else {
178: link.setResult(value);
179: }
180: } else {
181: throw new IllegalArgumentException(
182: "Cannot find child by name [" + name + "]");
183: }
184: }
185:
186: /**
187: *
188: * @param name
189: * @return Link by name
190: */
191: public Link getChild(String name) {
192: Link link = child(name);
193: invalidateNull(link, name);
194: return link;
195: }
196:
197: private void invalidateNull(Link link, String name) {
198: if (link == null) {
199: throw new IllegalArgumentException(
200: "Cannot find child by name [" + name + "]");
201: }
202: }
203:
204: /**
205: *
206: * @return LinkIterator
207: */
208: public LinkIterator linkIterator() {
209: return children == null ? LinkIterator.NULL_LINK_ITERATOR
210: : new LinkIterator(children);
211: }
212:
213: /**
214: * @see Parent#child(String)
215: */
216: public Link child(String name) {
217: return (Link) (children == null ? null : children.get(name));
218: }
219:
220: private void lazyChildrenInitialization() {
221: if (children == null) {
222: children = new LinkedHashMap();
223: }
224: }
225:
226: /**
227: *
228: * @return true if this parent has children
229: */
230: public boolean hasChildren() {
231: return children != null && children.size() > 0;
232: }
233:
234: /**
235: * Creates new instance of children map and "deep copies"
236: * all the values from the existing children
237: *
238: * @param parent
239: * @return new children map
240: */
241: public LinkedHashMap newChildren(Link parent) {
242: return newChildren0(parent, children);
243: }
244:
245: private LinkedHashMap newChildren0(Link parentLink,
246: LinkedHashMap oldChildren) {
247: LinkedHashMap newChildren = null;
248: if (oldChildren != null) {
249: newChildren = (LinkedHashMap) oldChildren.clone();
250: if (parentLink != null) {
251: parentLink.setChildren(newChildren);
252: }
253: for (Iterator it = newChildren.keySet().iterator(); it
254: .hasNext();) {
255: Object key = it.next();
256: Link oldLink = (Link) newChildren.get(key);
257: Link newLink = newChild(oldLink, key, newChildren);
258: newLink.setParentLink(parentLink);
259: newLink.setInlineMode(oldLink.getInlineMode());
260: if (oldLink != null && oldLink.hasChildren()) {
261: newChildren0(newLink, oldLink.getChildren());
262: }
263: }
264: }
265: return newChildren;
266: }
267:
268: private Link newChild(Link oldLink, Object key,
269: LinkedHashMap newChildren) {
270: Link newLink = oldLink.newInstance();
271: newChildren.put(key, newLink);
272: return newLink;
273: }
274:
275: private Link cloneChild(Object key, LinkedHashMap newChildren)
276: throws CloneNotSupportedException {
277: Link oldLink = (Link) newChildren.get(key);
278: Link newLink = (Link) oldLink.clone();
279: newChildren.put(key, newLink);
280: return oldLink;
281: }
282:
283: /**
284: * Performes "deep clone" of children
285: *
286: * @return cloned children map
287: * @throws CloneNotSupportedException
288: */
289: protected LinkedHashMap cloneChildren()
290: throws CloneNotSupportedException {
291: LinkedHashMap newChildren = null;
292: if (children != null) {
293: newChildren = (LinkedHashMap) children.clone();
294: for (Iterator it = newChildren.keySet().iterator(); it
295: .hasNext();) {
296: Object key = it.next();
297: cloneChild(key, newChildren);
298: }
299: }
300: return newChildren;
301: }
302:
303: /**
304: *
305: * @param buffer
306: * @return if buffer is null - empty string, otherwise - buffer.toString()
307: */
308: public static String buffer2string(StringBuffer buffer) {
309: return buffer == null ? "" : buffer.toString();
310: }
311:
312: /**
313: *
314: * @return inlineLinks
315: */
316: public Link[] inlineLinks() {
317: return getInlineLinks(this );
318: }
319:
320: /**
321: *
322: * @param parent
323: * @return inlineLinks
324: */
325: public static Link[] getInlineLinks(Parent parent) {
326: if (parent == null || !parent.hasChildren()) {
327: return null;
328: }
329: ArrayList inlineLinks = new ArrayList();
330: getInlineLinks0(parent, inlineLinks);
331: return (Link[]) inlineLinks
332: .toArray(new Link[inlineLinks.size()]);
333: }
334:
335: public static void getInlineLinks0(Parent parent, List inlineLinks) {
336: for (LinkIterator it = parent.linkIterator(); it.hasNext();) {
337: Link link = it.nextLink();
338: if (link.isInline()) {
339: inlineLinks.add(link);
340: }
341: }
342: }
343:
344: /**
345: *
346: * @return key of this object
347: */
348: public Object toKey() {
349: return this .getClass().getName();
350: }
351:
352: protected Map toMap() {
353: Map map = new LinkedHashMap();
354: Map childrenMap = new LinkedHashMap();
355: if (children != null && !children.isEmpty()) {
356: for (LinkIterator it = this .linkIterator(); it.hasNext();) {
357: Link child = it.nextLink();
358: Map childMap = child.toMap();
359: childrenMap.put(child.getName(), childMap);
360: }
361: map.put(TAG_CHILDREN, childrenMap);
362: }
363: return map;
364: }
365:
366: protected void fromMap(Map map) {
367: PropertyMap propertyMap = PropertyMap.toPropertyMap(map, true);
368: Map childrenMap = propertyMap.getPropertyMap(TAG_CHILDREN);
369: children = new LinkedHashMap();
370: if (childrenMap != null) {
371: for (Iterator it = childrenMap.keySet().iterator(); it
372: .hasNext();) {
373: String name = (String) it.next();
374: Map childMap = (Map) childrenMap.get(name);
375: Link link = new Link(childMap);
376: children.put(name, link);
377: }
378: }
379: }
380: }
|