Source Code Cross Referenced for AbstractGroup.java in  » Ajax » zk » org » zkoss » idom » impl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Ajax » zk » org.zkoss.idom.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /* AbstractGroup.java
002:
003:        {{IS_NOTE
004:
005:        	Purpose:
006:        	Description:
007:        	History:
008:        	2001/10/21 16:31:30, Create, Tom M. Yeh.
009:        }}IS_NOTE
010:
011:        Copyright (C) 2001 Potix Corporation. All Rights Reserved.
012:
013:        {{IS_RIGHT
014:        	This program is distributed under GPL Version 2.0 in the hope that
015:        	it will be useful, but WITHOUT ANY WARRANTY.
016:        }}IS_RIGHT
017:         */
018:        package org.zkoss.idom.impl;
019:
020:        import java.util.List;
021:        import java.util.ArrayList;
022:        import java.util.LinkedList;
023:        import java.util.Set;
024:        import java.util.LinkedHashSet;
025:        import java.util.Iterator;
026:        import java.util.ListIterator;
027:        import java.util.regex.Pattern;
028:        import java.util.Map;
029:        import java.util.LinkedHashMap;
030:        import java.util.Collection;
031:        import java.util.AbstractCollection;
032:        import java.util.Collections;
033:
034:        import org.w3c.dom.Node;
035:        import org.w3c.dom.NodeList;
036:
037:        import org.zkoss.util.CheckableTreeArray;
038:        import org.zkoss.xml.FacadeNodeList;
039:        import org.zkoss.idom.*;
040:
041:        /**
042:         * A semi-implemented item for group. A group is a item that has child items.
043:         *
044:         * <p>The default implementation of newChildren is for the sematic of
045:         * Element. A deriving class has to re-implement it, if it is not applicable.
046:         * Example, Document.
047:         *
048:         * @author tomyeh
049:         * @see Item
050:         */
051:        public abstract class AbstractGroup extends AbstractItem implements 
052:                Group {
053:            /** The list of the children. Never null.
054:             */
055:            protected List _children;
056:
057:            /** A helper map to enhance the searching speed with tag name.
058:             * If any deriving class don't contain this helper map, they should
059:             * apply the basic sequential search.
060:             */
061:            private transient ElementMap _elemMap;
062:
063:            /** Constructor.
064:             */
065:            protected AbstractGroup() {
066:                _children = newChildren();
067:            }
068:
069:            //-- deriving to override --//
070:            /** Creates a list to hold child vertices.
071:             * Note: the list must be able to protect itself from adding
072:             * unexpected child -- read-only, wrong type, undetached...
073:             *
074:             * <p>The default implementation obeys the sematic of Element,
075:             * i.e., it doen't allow any child that cannot be a child of Element.
076:             *
077:             * <p>For performance issue, we introduced a map to improve the search 
078:             * speed for Element node associated with a tag name.
079:             */
080:            protected List newChildren() {
081:                return new ChildArray();
082:            }
083:
084:            //-- Group --//
085:            public void clearModified(boolean includingDescendant) {
086:                if (includingDescendant) {
087:                    for (final Iterator it = _children.iterator(); it.hasNext();)
088:                        ((Item) it.next()).clearModified(true);
089:                }
090:                super .clearModified(includingDescendant);
091:            }
092:
093:            public Item clone(boolean preserveModified) {
094:                AbstractGroup group = (AbstractGroup) super 
095:                        .clone(preserveModified);
096:
097:                group._children = group.newChildren();
098:                for (final Iterator it = _children.iterator(); it.hasNext();) {
099:                    Item v = ((Item) it.next()).clone(preserveModified);
100:                    boolean bClearModified = !preserveModified
101:                            || !v.isModified();
102:
103:                    group._children.add(v); //v becomes modified (v.setParent is called)
104:
105:                    if (bClearModified)
106:                        v.clearModified(false);
107:                }
108:
109:                if (group._children instanceof  ChildArray)
110:                    ((ChildArray) group._children).afterClone();
111:
112:                group._modified = preserveModified && _modified;
113:                return group;
114:            }
115:
116:            public final List getChildren() {
117:                return _children;
118:            }
119:
120:            public final List detachChildren() {
121:                List list = new ArrayList(_children); //make a copy first
122:
123:                for (Iterator it = _children.iterator(); it.hasNext();) {
124:                    it.next();
125:                    it.remove(); //and detach
126:                }
127:
128:                return list;
129:            }
130:
131:            public final boolean anyElement() {
132:                if (_elemMap != null)
133:                    return _elemMap.any();
134:
135:                for (Iterator it = _children.iterator(); it.hasNext();) {
136:                    final Object o = it.next();
137:                    if (o instanceof  Element)
138:                        return true;
139:                }
140:                return false;
141:            }
142:
143:            public final Set getElementNames() {
144:                if (_elemMap != null)
145:                    return _elemMap.names();
146:
147:                final Set set = new LinkedHashSet();
148:                for (final Iterator it = _children.iterator(); it.hasNext();) {
149:                    final Object o = it.next();
150:                    if (o instanceof  Element)
151:                        set.add(((Element) o).getName());
152:                }
153:                return set;
154:            }
155:
156:            public final List getElements() {
157:                final List lst = new LinkedList();
158:                for (final Iterator it = _children.iterator(); it.hasNext();) {
159:                    final Object o = it.next();
160:                    if (o instanceof  Element)
161:                        lst.add(o);
162:                }
163:                return lst;
164:            }
165:
166:            public final int getElementIndex(int indexFrom, String namespace,
167:                    String name, int mode) {
168:                if (indexFrom < 0 || indexFrom >= _children.size())
169:                    return -1;
170:
171:                final Pattern ptn = (mode & FIND_BY_REGEX) != 0 ? Pattern
172:                        .compile(name) : null;
173:
174:                final Iterator it = _children.listIterator(indexFrom);
175:                for (int j = indexFrom; it.hasNext(); ++j) {
176:                    final Object o = it.next();
177:                    if ((o instanceof  Element)
178:                            && match((Element) o, namespace, name, ptn, mode))
179:                        return j;
180:                }
181:                return -1;
182:            }
183:
184:            public final int getElementIndex(int indexFrom, String tname) {
185:                return getElementIndex(indexFrom, null, tname, FIND_BY_TAGNAME);
186:            }
187:
188:            public final Element getElement(String namespace, String name,
189:                    int mode) {
190:                if (_elemMap != null && namespace == null
191:                        && mode == FIND_BY_TAGNAME)
192:                    return getElement(name); //use the speed version
193:
194:                int j = getElementIndex(0, namespace, name, mode);
195:                if (j >= 0)
196:                    return (Element) _children.get(j);
197:
198:                if ((mode & FIND_RECURSIVE) != 0) {
199:                    for (Iterator it = _children.iterator(); it.hasNext();) {
200:                        Object o = it.next();
201:                        if (o instanceof  Group) {
202:                            Element elem = ((Group) o).getElement(namespace,
203:                                    name, mode);
204:                            if (elem != null)
205:                                return elem;
206:                        }
207:                    }
208:                }
209:                return null;
210:            }
211:
212:            public final Element getElement(String tname) {
213:                if (_elemMap != null)
214:                    return _elemMap.get(tname);
215:
216:                int j = getElementIndex(0, tname);
217:                return j >= 0 ? (Element) _children.get(j) : null;
218:            }
219:
220:            public final List getElements(String namespace, String name,
221:                    int mode) {
222:                if (_elemMap != null && namespace == null
223:                        && mode == FIND_BY_TAGNAME)
224:                    return getElements(name); //use the speed version
225:
226:                final Pattern ptn = (mode & FIND_BY_REGEX) != 0 ? Pattern
227:                        .compile(name) : null;
228:
229:                final List list = new LinkedList();
230:                for (final Iterator it = _children.iterator(); it.hasNext();) {
231:                    Object o = it.next();
232:                    if ((o instanceof  Element)
233:                            && match((Element) o, namespace, name, ptn, mode))
234:                        list.add(o);
235:                }
236:
237:                if ((mode & FIND_RECURSIVE) != 0) {
238:                    for (final Iterator it = _children.iterator(); it.hasNext();) {
239:                        Object o = it.next();
240:                        if (o instanceof  Group)
241:                            list.addAll(((Group) o).getElements(namespace,
242:                                    name, mode));
243:                    }
244:                }
245:                return list;
246:            }
247:
248:            public final List getElements(String tname) {
249:                if (_elemMap != null)
250:                    return _elemMap.getAll(tname);
251:
252:                return getElements(null, tname, FIND_BY_TAGNAME);
253:            }
254:
255:            public final String getElementValue(String namespace, String name,
256:                    int mode, boolean trim) {
257:                Element child = getElement(namespace, name, mode);
258:                return child != null ? child.getText(trim) : null;
259:            }
260:
261:            public final String getElementValue(String tname, boolean trim) {
262:                final Element child = getElement(tname);
263:                return child != null ? child.getText(trim) : null;
264:            }
265:
266:            public final int coalesce(boolean recursive) {
267:                int count = 0;
268:                Item found = null;
269:                StringBuffer sb = new StringBuffer();
270:                for (final Iterator it = _children.iterator(); it.hasNext();) {
271:                    Object o = it.next();
272:                    Item newFound = (o instanceof  Textual)
273:                            && ((Textual) o).isCoalesceable() ? (Item) o : null;
274:
275:                    if (newFound != null && found != null
276:                            && found.getClass().equals(o.getClass())) {
277:                        if (sb.length() == 0)
278:                            sb.append(found.getText());
279:                        sb.append(((Item) o).getText()); //coalesce text
280:                        it.remove(); //remove this node
281:                        ++count; //# being coalesced and removed
282:                    } else {
283:                        if (sb.length() > 0) { //coalesced before?
284:                            found.setText(sb.toString());
285:                            sb.setLength(0);
286:                        }
287:                        found = newFound;
288:                    }
289:                }
290:                if (sb.length() > 0)
291:                    found.setText(sb.toString());
292:                sb = null; //no longer useful
293:
294:                if (recursive) {
295:                    for (final Iterator it = _children.iterator(); it.hasNext();) {
296:                        final Object o = it.next();
297:                        if (o instanceof  Group)
298:                            count += ((Group) o).coalesce(recursive);
299:                    }
300:                }
301:                return count;
302:            }
303:
304:            //-- Node --//
305:            public final NodeList getChildNodes() {
306:                return new FacadeNodeList(_children);
307:            }
308:
309:            public final Node getFirstChild() {
310:                return _children.isEmpty() ? null : (Node) _children.get(0);
311:            }
312:
313:            public final Node getLastChild() {
314:                int sz = _children.size();
315:                return sz == 0 ? null : (Node) _children.get(sz - 1);
316:            }
317:
318:            public final boolean hasChildNodes() {
319:                return !_children.isEmpty();
320:            }
321:
322:            //No need to call checkWritable here because _children is smart enough
323:            public final Node insertBefore(Node newChild, Node refChild) {
324:                if (refChild == null)
325:                    return appendChild(newChild);
326:
327:                int j = _children.indexOf(refChild);
328:                if (j < 0)
329:                    throw new DOMException(DOMException.NOT_FOUND_ERR,
330:                            getLocator());
331:                _children.add(j, newChild);
332:                return newChild;
333:            }
334:
335:            public final Node replaceChild(Node newChild, Node oldChild) {
336:                int j = _children.indexOf(oldChild);
337:                if (j < 0)
338:                    throw new DOMException(DOMException.NOT_FOUND_ERR,
339:                            getLocator());
340:                return (Node) _children.set(j, newChild);
341:            }
342:
343:            public final Node removeChild(Node oldChild) {
344:                int j = _children.indexOf(oldChild);
345:                if (j < 0)
346:                    throw new DOMException(DOMException.NOT_FOUND_ERR,
347:                            getLocator());
348:                return (Node) _children.remove(j);
349:            }
350:
351:            public final Node appendChild(Node newChild) {
352:                _children.add(newChild);
353:                return newChild;
354:            }
355:
356:            //-- Serializable --//
357:            //NOTE: they must be declared as private
358:            private synchronized void readObject(java.io.ObjectInputStream s)
359:                    throws java.io.IOException, ClassNotFoundException {
360:                s.defaultReadObject();
361:
362:                if (_children instanceof  ChildArray)
363:                    ((ChildArray) _children).afterUnmarshal();
364:            }
365:
366:            //-- ElementMap
367:            /** Stores a 'cached' map of child elements to speed up the access.
368:             */
369:            protected static class ElementMap {
370:                /** the map of (String elemName, List of Elements). */
371:                private final Map _map = new LinkedHashMap();
372:
373:                protected ElementMap() {
374:                }
375:
376:                /**
377:                 * Put an element into the map.
378:                 * If the "following" argument is assocaied the same name, we will
379:                 * add the element before the "following".
380:                 */
381:                public final void put(Element e, Element following) {
382:                    final String name = e.getName();
383:                    List valueList = (List) _map.get(name);
384:                    if (valueList == null) {
385:                        valueList = new LinkedList();
386:                        _map.put(name, valueList);
387:                    }
388:
389:                    if (following != null && name.equals(following.getName())) {
390:                        //add into list before the following
391:                        for (ListIterator it = valueList.listIterator(); it
392:                                .hasNext();) {
393:                            if (it.next() == following) { //no need to use equals
394:                                it.previous();
395:                                it.add(e);
396:                                return;
397:                            }
398:                        }
399:                    }
400:
401:                    valueList.add(e); //add into list
402:                }
403:
404:                /**
405:                 * Get the element with name. If you have many values associalted with
406:                 * the same key, it returned the head for you.
407:                 */
408:                public final Element get(String name) {
409:                    final List vals = (List) _map.get(name);
410:                    return vals != null && !vals.isEmpty() ? (Element) vals
411:                            .get(0) : null;
412:                }
413:
414:                /**
415:                 * Get a readonly list of all elements with name.
416:                 */
417:                public final List getAll(String name) {
418:                    final List vals = (List) _map.get(name);
419:                    return vals != null ? Collections.unmodifiableList(vals)
420:                            : Collections.EMPTY_LIST;
421:                }
422:
423:                /**
424:                 * Remove e from the map.
425:                 */
426:                public final void remove(Element e) {
427:                    final List vals = (List) _map.get(e.getName());
428:                    vals.remove(e);
429:                    if (vals.isEmpty())
430:                        _map.remove(e.getName());
431:                }
432:
433:                /** Returns true if any element.
434:                 */
435:                public final boolean any() {
436:                    return !_map.isEmpty();
437:                }
438:
439:                /** Returns a readonly set of names of all elements.
440:                 */
441:                public final Set names() {
442:                    return _map.keySet();
443:                }
444:
445:                /** Returns the number of elements.
446:                 */
447:                public final int size() {
448:                    int sz = 0;
449:                    for (Iterator it = _map.values().iterator(); it.hasNext();) {
450:                        sz += ((List) it.next()).size();
451:                    }
452:                    return sz;
453:                }
454:            }
455:
456:            //-- ChildArray --//
457:            /** The array to hold children.
458:             */
459:            protected class ChildArray extends CheckableTreeArray {
460:                protected ChildArray() {
461:                    _elemMap = new ElementMap();
462:                }
463:
464:                /** Called after unmarshalling back the AbstractGroup instance
465:                 * that owns this object.
466:                 */
467:                private void afterUnmarshal() {
468:                    _elemMap = new ElementMap();
469:
470:                    for (Iterator it = this .iterator(); it.hasNext();) {
471:                        final Object o = it.next();
472:                        if (o instanceof  Element)
473:                            _elemMap.put((Element) o, null);
474:                    }
475:                }
476:
477:                /** Called after cloning the AbstractGroup instance that owns this object.
478:                 */
479:                private void afterClone() {
480:                    afterUnmarshal();
481:                }
482:
483:                //-- CheckableTreeArray --//
484:                protected void onAdd(Object newElement, Object followingElement) {
485:                    checkAdd(newElement, followingElement, false);
486:                }
487:
488:                protected void onSet(Object newElement, Object replaced) {
489:                    assert (replaced != null);
490:                    checkAdd(newElement, replaced, true);
491:                }
492:
493:                private void checkAdd(Object newVal, Object other,
494:                        boolean replace) {
495:                    checkWritable();
496:
497:                    //allowed type?
498:                    if (!(newVal instanceof  Element)
499:                            && !(newVal instanceof  Text)
500:                            && !(newVal instanceof  CData)
501:                            && !(newVal instanceof  Comment)
502:                            && !(newVal instanceof  EntityReference)
503:                            && !(newVal instanceof  Binary)
504:                            && !(newVal instanceof  ProcessingInstruction))
505:                        throw new DOMException(
506:                                DOMException.HIERARCHY_REQUEST_ERR,
507:                                "Invalid type", getLocator());
508:
509:                    //to be safe, no auto-detach
510:                    final Item newItem = (Item) newVal;
511:                    if (newItem.getParent() != null) {
512:                        throw new DOMException(
513:                                DOMException.HIERARCHY_REQUEST_ERR, "Item, "
514:                                        + newItem.toString() + ", owned by "
515:                                        + newItem.getParent() + " "
516:                                        + newItem.getLocator()
517:                                        + "; detach or clone it", getLocator());
518:                    }
519:
520:                    //test whether a graph will be created?
521:                    if (newItem instanceof  Group)
522:                        for (Item p = AbstractGroup.this ; p != null; p = p
523:                                .getParent())
524:                            if (p == newItem)
525:                                throw new DOMException(
526:                                        DOMException.HIERARCHY_REQUEST_ERR,
527:                                        "Add to itself", getLocator());
528:
529:                    if (newItem instanceof  Element) { //Element put into map, this must be done before replaced
530:                        //try to find the first Element node on the array
531:                        Element eOther;
532:                        if ((other != null) && !(other instanceof  Element)) {
533:                            eOther = null;
534:                            boolean bFirstElemFind = false;
535:                            for (Iterator it = this .iterator(); it.hasNext();) {
536:                                Object node = it.next();
537:                                if (bFirstElemFind) {
538:                                    if (node instanceof  Element) {
539:                                        eOther = (Element) node;
540:                                        break;
541:                                    }
542:                                } else if (node == other) {
543:                                    bFirstElemFind = true;
544:                                }
545:                            }
546:                        } else {
547:                            eOther = (Element) other;
548:                        }
549:                        _elemMap.put((Element) newItem, eOther);
550:                    }
551:
552:                    if (replace)
553:                        onRemove(other);
554:                    newItem.setParent(AbstractGroup.this ); //it will call this.setModified
555:                }
556:
557:                protected void onRemove(Object item) {
558:                    checkWritable();
559:                    final Item removeItem = (Item) item;
560:                    removeItem.setParent(null); //it will call this.setModified
561:
562:                    if (removeItem instanceof  Element) //Element remove from map
563:                        _elemMap.remove((Element) removeItem);
564:                }
565:            }
566:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.