Source Code Cross Referenced for DefaultXBLManager.java in  » Graphic-Library » batik » org » apache » batik » bridge » svg12 » 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 » Graphic Library » batik » org.apache.batik.bridge.svg12 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Licensed to the Apache Software Foundation (ASF) under one or more
0004:           contributor license agreements.  See the NOTICE file distributed with
0005:           this work for additional information regarding copyright ownership.
0006:           The ASF licenses this file to You under the Apache License, Version 2.0
0007:           (the "License"); you may not use this file except in compliance with
0008:           the License.  You may obtain a copy of the License at
0009:
0010:               http://www.apache.org/licenses/LICENSE-2.0
0011:
0012:           Unless required by applicable law or agreed to in writing, software
0013:           distributed under the License is distributed on an "AS IS" BASIS,
0014:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0015:           See the License for the specific language governing permissions and
0016:           limitations under the License.
0017:
0018:         */
0019:        package org.apache.batik.bridge.svg12;
0020:
0021:        import java.util.ArrayList;
0022:        import java.util.HashMap;
0023:        import java.util.Iterator;
0024:        import java.util.LinkedList;
0025:        import java.util.Set;
0026:        import java.util.TreeSet;
0027:        import java.util.List;
0028:        import java.util.Map;
0029:
0030:        import javax.swing.event.EventListenerList;
0031:
0032:        import org.apache.batik.bridge.BridgeContext;
0033:        import org.apache.batik.bridge.BridgeException;
0034:        import org.apache.batik.bridge.ErrorConstants;
0035:        import org.apache.batik.dom.AbstractAttrNS;
0036:        import org.apache.batik.dom.AbstractDocument;
0037:        import org.apache.batik.dom.AbstractNode;
0038:        import org.apache.batik.dom.events.NodeEventTarget;
0039:        import org.apache.batik.dom.svg12.BindableElement;
0040:        import org.apache.batik.dom.svg12.XBLEventSupport;
0041:        import org.apache.batik.dom.svg12.XBLOMContentElement;
0042:        import org.apache.batik.dom.svg12.XBLOMDefinitionElement;
0043:        import org.apache.batik.dom.svg12.XBLOMImportElement;
0044:        import org.apache.batik.dom.svg12.XBLOMShadowTreeElement;
0045:        import org.apache.batik.dom.svg12.XBLOMTemplateElement;
0046:        import org.apache.batik.dom.util.DoublyIndexedTable;
0047:        import org.apache.batik.dom.xbl.NodeXBL;
0048:        import org.apache.batik.dom.xbl.ShadowTreeEvent;
0049:        import org.apache.batik.dom.xbl.XBLManager;
0050:        import org.apache.batik.dom.xbl.XBLManagerData;
0051:        import org.apache.batik.dom.xbl.XBLShadowTreeElement;
0052:        import org.apache.batik.util.XBLConstants;
0053:        import org.apache.batik.util.XMLConstants;
0054:
0055:        import org.w3c.dom.Attr;
0056:        import org.w3c.dom.Document;
0057:        import org.w3c.dom.Element;
0058:        import org.w3c.dom.NamedNodeMap;
0059:        import org.w3c.dom.Node;
0060:        import org.w3c.dom.NodeList;
0061:        import org.w3c.dom.events.DocumentEvent;
0062:        import org.w3c.dom.events.Event;
0063:        import org.w3c.dom.events.EventListener;
0064:        import org.w3c.dom.events.EventTarget;
0065:        import org.w3c.dom.events.MutationEvent;
0066:
0067:        /**
0068:         * A full featured sXBL manager.
0069:         *
0070:         * @author <a href="mailto:cam%40mcc%2eid%2eau">Cameron McCormack</a>
0071:         * @version $Id: DefaultXBLManager.java 479559 2006-11-27 09:46:16Z dvholten $
0072:         */
0073:        public class DefaultXBLManager implements  XBLManager, XBLConstants {
0074:
0075:            /**
0076:             * Whether XBL processing is currently taking place.
0077:             */
0078:            protected boolean isProcessing;
0079:
0080:            /**
0081:             * The document.
0082:             */
0083:            protected Document document;
0084:
0085:            /**
0086:             * The BridgeContext.
0087:             */
0088:            protected BridgeContext ctx;
0089:
0090:            /**
0091:             * Map of namespace URI/local name pairs to ordered sets of
0092:             * definition records.
0093:             */
0094:            protected DoublyIndexedTable definitionLists = new DoublyIndexedTable();
0095:
0096:            /**
0097:             * Map of definition element/import element pairs to definition records.
0098:             */
0099:            protected DoublyIndexedTable definitions = new DoublyIndexedTable();
0100:
0101:            /**
0102:             * Map of shadow trees to content managers.
0103:             */
0104:            protected Map contentManagers = new HashMap();
0105:
0106:            /**
0107:             * Map of import elements to import records.
0108:             */
0109:            protected Map imports = new HashMap();
0110:
0111:            /**
0112:             * DOM node inserted listener for the document.
0113:             */
0114:            protected DocInsertedListener docInsertedListener = new DocInsertedListener();
0115:
0116:            /**
0117:             * DOM node removed listener for the document.
0118:             */
0119:            protected DocRemovedListener docRemovedListener = new DocRemovedListener();
0120:
0121:            /**
0122:             * DOM subtree mutation listener for the document.
0123:             */
0124:            protected DocSubtreeListener docSubtreeListener = new DocSubtreeListener();
0125:
0126:            /**
0127:             * DOM attribute listener for import elements.
0128:             */
0129:            protected ImportAttrListener importAttrListener = new ImportAttrListener();
0130:
0131:            /**
0132:             * DOM attribute listener for referencing definition elements.
0133:             */
0134:            protected RefAttrListener refAttrListener = new RefAttrListener();
0135:
0136:            /**
0137:             * Global event listener list for XBL binding related events.
0138:             */
0139:            protected EventListenerList bindingListenerList = new EventListenerList();
0140:
0141:            /**
0142:             * Global event listener list for ContentSelectionChanged events.
0143:             */
0144:            protected EventListenerList contentSelectionChangedListenerList = new EventListenerList();
0145:
0146:            /**
0147:             * Creates a new DefaultXBLManager for the given document.
0148:             */
0149:            public DefaultXBLManager(Document doc, BridgeContext ctx) {
0150:                document = doc;
0151:                this .ctx = ctx;
0152:                ImportRecord ir = new ImportRecord(null, null);
0153:                imports.put(null, ir);
0154:            }
0155:
0156:            /**
0157:             * Starts XBL processing on the document.
0158:             */
0159:            public void startProcessing() {
0160:                if (isProcessing) {
0161:                    return;
0162:                }
0163:
0164:                // Get list of all current definitions in the document.
0165:                NodeList nl = document.getElementsByTagNameNS(
0166:                        XBL_NAMESPACE_URI, XBL_DEFINITION_TAG);
0167:                XBLOMDefinitionElement[] defs = new XBLOMDefinitionElement[nl
0168:                        .getLength()];
0169:                for (int i = 0; i < defs.length; i++) {
0170:                    defs[i] = (XBLOMDefinitionElement) nl.item(i);
0171:                }
0172:
0173:                // Get list of all imports in the document.
0174:                nl = document.getElementsByTagNameNS(XBL_NAMESPACE_URI,
0175:                        XBL_IMPORT_TAG);
0176:                Element[] imports = new Element[nl.getLength()];
0177:                for (int i = 0; i < imports.length; i++) {
0178:                    imports[i] = (Element) nl.item(i);
0179:                }
0180:
0181:                // Add document listeners.
0182:                AbstractDocument doc = (AbstractDocument) document;
0183:                XBLEventSupport es = (XBLEventSupport) doc
0184:                        .initializeEventSupport();
0185:                es.addImplementationEventListenerNS(
0186:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0187:                        "DOMNodeRemoved", docRemovedListener, true);
0188:                es.addImplementationEventListenerNS(
0189:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0190:                        "DOMNodeInserted", docInsertedListener, true);
0191:                es.addImplementationEventListenerNS(
0192:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0193:                        "DOMSubtreeModified", docSubtreeListener, true);
0194:
0195:                // Add definitions.
0196:                for (int i = 0; i < defs.length; i++) {
0197:                    if (defs[i].getAttributeNS(null, XBL_REF_ATTRIBUTE)
0198:                            .length() != 0) {
0199:                        addDefinitionRef(defs[i]);
0200:                    } else {
0201:                        String ns = defs[i].getElementNamespaceURI();
0202:                        String ln = defs[i].getElementLocalName();
0203:                        addDefinition(ns, ln, defs[i], null);
0204:                    }
0205:                }
0206:
0207:                // Add imports.
0208:                for (int i = 0; i < imports.length; i++) {
0209:                    addImport(imports[i]);
0210:                }
0211:
0212:                // Bind all of the bindable elements in the document that have a
0213:                // matching definition.
0214:                isProcessing = true;
0215:                bind(document.getDocumentElement());
0216:            }
0217:
0218:            /**
0219:             * Stops XBL processing on the document.
0220:             */
0221:            public void stopProcessing() {
0222:                if (!isProcessing) {
0223:                    return;
0224:                }
0225:                isProcessing = false;
0226:
0227:                // Remove document listeners.
0228:                AbstractDocument doc = (AbstractDocument) document;
0229:                XBLEventSupport es = (XBLEventSupport) doc
0230:                        .initializeEventSupport();
0231:                es.removeImplementationEventListenerNS(
0232:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0233:                        "DOMNodeRemoved", docRemovedListener, true);
0234:                es.removeImplementationEventListenerNS(
0235:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0236:                        "DOMNodeInserted", docInsertedListener, true);
0237:                es.removeImplementationEventListenerNS(
0238:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0239:                        "DOMSubtreeModified", docSubtreeListener, true);
0240:
0241:                // Remove all imports.
0242:                int nSlots = imports.values().size();
0243:                ImportRecord[] irs = new ImportRecord[nSlots];
0244:                imports.values().toArray(irs);
0245:                for (int i = 0; i < irs.length; i++) {
0246:                    ImportRecord ir = irs[i];
0247:                    if (ir.importElement.getLocalName().equals(
0248:                            XBL_DEFINITION_TAG)) {
0249:                        removeDefinitionRef(ir.importElement);
0250:                    } else {
0251:                        removeImport(ir.importElement);
0252:                    }
0253:                }
0254:
0255:                // Remove all bindings.
0256:                Object[] defRecs = definitions.getValuesArray();
0257:                definitions.clear();
0258:                for (int i = 0; i < defRecs.length; i++) {
0259:                    DefinitionRecord defRec = (DefinitionRecord) defRecs[i];
0260:                    TreeSet defs = (TreeSet) definitionLists.get(
0261:                            defRec.namespaceURI, defRec.localName);
0262:                    if (defs != null) {
0263:                        while (!defs.isEmpty()) {
0264:                            defRec = (DefinitionRecord) defs.first();
0265:                            defs.remove(defRec);
0266:                            removeDefinition(defRec);
0267:                        }
0268:                        definitionLists.put(defRec.namespaceURI,
0269:                                defRec.localName, null);
0270:                    }
0271:                }
0272:                definitionLists = new DoublyIndexedTable();
0273:                contentManagers.clear();
0274:            }
0275:
0276:            /**
0277:             * Returns whether XBL processing is currently enabled.
0278:             */
0279:            public boolean isProcessing() {
0280:                return isProcessing;
0281:            }
0282:
0283:            /**
0284:             * Adds a definition through its referring definition element (one
0285:             * with a 'ref' attribute).
0286:             */
0287:            protected void addDefinitionRef(Element defRef) {
0288:                String ref = defRef.getAttributeNS(null, XBL_REF_ATTRIBUTE);
0289:                Element e = ctx.getReferencedElement(defRef, ref);
0290:                if (!XBL_NAMESPACE_URI.equals(e.getNamespaceURI())
0291:                        || !XBL_DEFINITION_TAG.equals(e.getLocalName())) {
0292:                    throw new BridgeException(ctx, defRef,
0293:                            ErrorConstants.ERR_URI_BAD_TARGET,
0294:                            new Object[] { ref });
0295:                }
0296:                ImportRecord ir = new ImportRecord(defRef, e);
0297:                imports.put(defRef, ir);
0298:
0299:                NodeEventTarget et = (NodeEventTarget) defRef;
0300:                et.addEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
0301:                        "DOMAttrModified", refAttrListener, false, null);
0302:
0303:                XBLOMDefinitionElement d = (XBLOMDefinitionElement) defRef;
0304:                String ns = d.getElementNamespaceURI();
0305:                String ln = d.getElementLocalName();
0306:                addDefinition(ns, ln, (XBLOMDefinitionElement) e, defRef);
0307:            }
0308:
0309:            /**
0310:             * Removes a definition through its referring definition element (one
0311:             * with a 'ref' attribute).
0312:             */
0313:            protected void removeDefinitionRef(Element defRef) {
0314:                ImportRecord ir = (ImportRecord) imports.get(defRef);
0315:                NodeEventTarget et = (NodeEventTarget) defRef;
0316:                et.removeEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
0317:                        "DOMAttrModified", refAttrListener, false);
0318:                DefinitionRecord defRec = (DefinitionRecord) definitions.get(
0319:                        ir.node, defRef);
0320:                removeDefinition(defRec);
0321:                imports.remove(defRef);
0322:            }
0323:
0324:            /**
0325:             * Imports bindings from another document.
0326:             */
0327:            protected void addImport(Element imp) {
0328:                String bindings = imp.getAttributeNS(null,
0329:                        XBL_BINDINGS_ATTRIBUTE);
0330:                Node n = ctx.getReferencedNode(imp, bindings);
0331:                if (n.getNodeType() == Node.ELEMENT_NODE
0332:                        && !(XBL_NAMESPACE_URI.equals(n.getNamespaceURI()) && XBL_XBL_TAG
0333:                                .equals(n.getLocalName()))) {
0334:                    throw new BridgeException(ctx, imp,
0335:                            ErrorConstants.ERR_URI_BAD_TARGET,
0336:                            new Object[] { n });
0337:                }
0338:                ImportRecord ir = new ImportRecord(imp, n);
0339:                imports.put(imp, ir);
0340:
0341:                NodeEventTarget et = (NodeEventTarget) imp;
0342:                et.addEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
0343:                        "DOMAttrModified", importAttrListener, false, null);
0344:
0345:                et = (NodeEventTarget) n;
0346:                et.addEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
0347:                        "DOMNodeInserted", ir.importInsertedListener, false,
0348:                        null);
0349:                et
0350:                        .addEventListenerNS(
0351:                                XMLConstants.XML_EVENTS_NAMESPACE_URI,
0352:                                "DOMNodeRemoved", ir.importRemovedListener,
0353:                                false, null);
0354:                et.addEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
0355:                        "DOMSubtreeModified", ir.importSubtreeListener, false,
0356:                        null);
0357:                addImportedDefinitions(imp, n);
0358:            }
0359:
0360:            /**
0361:             * Adds the definitions in the given imported subtree.
0362:             */
0363:            protected void addImportedDefinitions(Element imp, Node n) {
0364:                if (n instanceof  XBLOMDefinitionElement) {
0365:                    XBLOMDefinitionElement def = (XBLOMDefinitionElement) n;
0366:                    String ns = def.getElementNamespaceURI();
0367:                    String ln = def.getElementLocalName();
0368:                    addDefinition(ns, ln, def, imp);
0369:                } else {
0370:                    n = n.getFirstChild();
0371:                    while (n != null) {
0372:                        addImportedDefinitions(imp, n);
0373:                        n = n.getNextSibling();
0374:                    }
0375:                }
0376:            }
0377:
0378:            /**
0379:             * Removes an import.
0380:             */
0381:            protected void removeImport(Element imp) {
0382:                ImportRecord ir = (ImportRecord) imports.get(imp);
0383:                NodeEventTarget et = (NodeEventTarget) ir.node;
0384:                et.removeEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
0385:                        "DOMNodeInserted", ir.importInsertedListener, false);
0386:                et.removeEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
0387:                        "DOMNodeRemoved", ir.importRemovedListener, false);
0388:                et.removeEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
0389:                        "DOMSubtreeModified", ir.importSubtreeListener, false);
0390:
0391:                et = (NodeEventTarget) imp;
0392:                et.removeEventListenerNS(XMLConstants.XML_EVENTS_NAMESPACE_URI,
0393:                        "DOMAttrModified", importAttrListener, false);
0394:
0395:                Object[] defRecs = definitions.getValuesArray();
0396:                for (int i = 0; i < defRecs.length; i++) {
0397:                    DefinitionRecord defRec = (DefinitionRecord) defRecs[i];
0398:                    if (defRec.importElement == imp) {
0399:                        removeDefinition(defRec);
0400:                    }
0401:                }
0402:                imports.remove(imp);
0403:            }
0404:
0405:            /**
0406:             * Adds an xbl:definition element to the list of definitions that
0407:             * could possibly affect elements with the specified QName.  This
0408:             * may or may not actually cause a new binding to come in to effect,
0409:             * as this new definition element may be added earlier in the
0410:             * document than another already in effect.
0411:             *
0412:             * @param namespaceURI the namespace URI of the bound elements
0413:             * @param localName the local name of the bound elements
0414:             * @param def the xbl:definition element
0415:             * @param imp the xbl:import or xbl;definition element through which
0416:             *            this definition is being added, or null if the binding
0417:             *            is in the original document
0418:             */
0419:            protected void addDefinition(String namespaceURI, String localName,
0420:                    XBLOMDefinitionElement def, Element imp) {
0421:                ImportRecord ir = (ImportRecord) imports.get(imp);
0422:                DefinitionRecord oldDefRec = null;
0423:                DefinitionRecord defRec;
0424:                TreeSet defs = (TreeSet) definitionLists.get(namespaceURI,
0425:                        localName);
0426:                if (defs == null) {
0427:                    defs = new TreeSet();
0428:                    definitionLists.put(namespaceURI, localName, defs);
0429:                } else if (defs.size() > 0) {
0430:                    oldDefRec = (DefinitionRecord) defs.first();
0431:                }
0432:                XBLOMTemplateElement template = null;
0433:                for (Node n = def.getFirstChild(); n != null; n = n
0434:                        .getNextSibling()) {
0435:                    if (n instanceof  XBLOMTemplateElement) {
0436:                        template = (XBLOMTemplateElement) n;
0437:                        break;
0438:                    }
0439:                }
0440:                defRec = new DefinitionRecord(namespaceURI, localName, def,
0441:                        template, imp);
0442:                defs.add(defRec);
0443:                definitions.put(def, imp, defRec);
0444:                addDefinitionElementListeners(def, ir);
0445:                if (defs.first() != defRec) {
0446:                    return;
0447:                }
0448:                if (oldDefRec != null) {
0449:                    XBLOMDefinitionElement oldDef = oldDefRec.definition;
0450:                    XBLOMTemplateElement oldTemplate = oldDefRec.template;
0451:                    if (oldTemplate != null) {
0452:                        removeTemplateElementListeners(oldTemplate, ir);
0453:                    }
0454:                    removeDefinitionElementListeners(oldDef, ir);
0455:                }
0456:                if (template != null) {
0457:                    addTemplateElementListeners(template, ir);
0458:                }
0459:                if (isProcessing) {
0460:                    rebind(namespaceURI, localName, document
0461:                            .getDocumentElement());
0462:                }
0463:            }
0464:
0465:            /**
0466:             * Adds DOM mutation listeners to the given definition element.
0467:             */
0468:            protected void addDefinitionElementListeners(
0469:                    XBLOMDefinitionElement def, ImportRecord ir) {
0470:                XBLEventSupport es = (XBLEventSupport) def
0471:                        .initializeEventSupport();
0472:                es.addImplementationEventListenerNS(
0473:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0474:                        "DOMAttrModified", ir.defAttrListener, false);
0475:                es.addImplementationEventListenerNS(
0476:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0477:                        "DOMNodeInserted", ir.defNodeInsertedListener, false);
0478:                es.addImplementationEventListenerNS(
0479:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0480:                        "DOMNodeRemoved", ir.defNodeRemovedListener, false);
0481:            }
0482:
0483:            /**
0484:             * Adds DOM mutation listeners to the given template element.
0485:             */
0486:            protected void addTemplateElementListeners(
0487:                    XBLOMTemplateElement template, ImportRecord ir) {
0488:                XBLEventSupport es = (XBLEventSupport) template
0489:                        .initializeEventSupport();
0490:                es.addImplementationEventListenerNS(
0491:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0492:                        "DOMAttrModified", ir.templateMutationListener, false);
0493:                es.addImplementationEventListenerNS(
0494:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0495:                        "DOMNodeInserted", ir.templateMutationListener, false);
0496:                es.addImplementationEventListenerNS(
0497:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0498:                        "DOMNodeRemoved", ir.templateMutationListener, false);
0499:                es.addImplementationEventListenerNS(
0500:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0501:                        "DOMCharacterDataModified",
0502:                        ir.templateMutationListener, false);
0503:            }
0504:
0505:            /**
0506:             * Removes an xbl:definition element from the list of definitions that
0507:             * could possibly affect elements with the specified QName.  This
0508:             * will only cause a new binding to come in to effect if it is currently
0509:             * active.
0510:             */
0511:            protected void removeDefinition(DefinitionRecord defRec) {
0512:                TreeSet defs = (TreeSet) definitionLists.get(
0513:                        defRec.namespaceURI, defRec.localName);
0514:                if (defs == null) {
0515:                    return;
0516:                }
0517:                Element imp = defRec.importElement;
0518:                ImportRecord ir = (ImportRecord) imports.get(imp);
0519:                DefinitionRecord activeDefRec = (DefinitionRecord) defs.first();
0520:                defs.remove(defRec);
0521:                definitions.remove(defRec.definition, imp);
0522:                removeDefinitionElementListeners(defRec.definition, ir);
0523:                if (defRec != activeDefRec) {
0524:                    return;
0525:                }
0526:                if (defRec.template != null) {
0527:                    removeTemplateElementListeners(defRec.template, ir);
0528:                }
0529:                rebind(defRec.namespaceURI, defRec.localName, document
0530:                        .getDocumentElement());
0531:            }
0532:
0533:            /**
0534:             * Removes DOM mutation listeners from the given definition element.
0535:             */
0536:            protected void removeDefinitionElementListeners(
0537:                    XBLOMDefinitionElement def, ImportRecord ir) {
0538:                XBLEventSupport es = (XBLEventSupport) def
0539:                        .initializeEventSupport();
0540:                es.removeImplementationEventListenerNS(
0541:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0542:                        "DOMAttrModified", ir.defAttrListener, false);
0543:                es.removeImplementationEventListenerNS(
0544:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0545:                        "DOMNodeInserted", ir.defNodeInsertedListener, false);
0546:                es.removeImplementationEventListenerNS(
0547:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0548:                        "DOMNodeRemoved", ir.defNodeRemovedListener, false);
0549:            }
0550:
0551:            /**
0552:             * Removes DOM mutation listeners from the given template element.
0553:             */
0554:            protected void removeTemplateElementListeners(
0555:                    XBLOMTemplateElement template, ImportRecord ir) {
0556:                XBLEventSupport es = (XBLEventSupport) template
0557:                        .initializeEventSupport();
0558:                es.removeImplementationEventListenerNS(
0559:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0560:                        "DOMAttrModified", ir.templateMutationListener, false);
0561:                es.removeImplementationEventListenerNS(
0562:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0563:                        "DOMNodeInserted", ir.templateMutationListener, false);
0564:                es.removeImplementationEventListenerNS(
0565:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0566:                        "DOMNodeRemoved", ir.templateMutationListener, false);
0567:                es.removeImplementationEventListenerNS(
0568:                        XMLConstants.XML_EVENTS_NAMESPACE_URI,
0569:                        "DOMCharacterDataModified",
0570:                        ir.templateMutationListener, false);
0571:            }
0572:
0573:            /**
0574:             * Returns the definition record of the active definition for namespace
0575:             * URI/local name pair.
0576:             */
0577:            protected DefinitionRecord getActiveDefinition(String namespaceURI,
0578:                    String localName) {
0579:                TreeSet defs = (TreeSet) definitionLists.get(namespaceURI,
0580:                        localName);
0581:                if (defs == null || defs.size() == 0) {
0582:                    return null;
0583:                }
0584:                return (DefinitionRecord) defs.first();
0585:            }
0586:
0587:            /**
0588:             * Unbinds each bindable element in the given element's subtree.
0589:             */
0590:            protected void unbind(Element e) {
0591:                if (e instanceof  BindableElement) {
0592:                    setActiveDefinition((BindableElement) e, null);
0593:                } else {
0594:                    NodeList nl = getXblScopedChildNodes(e);
0595:                    for (int i = 0; i < nl.getLength(); i++) {
0596:                        Node n = nl.item(i);
0597:                        if (n.getNodeType() == Node.ELEMENT_NODE) {
0598:                            unbind((Element) n);
0599:                        }
0600:                    }
0601:                }
0602:            }
0603:
0604:            /**
0605:             * Binds each bindable element in the given element's subtree.
0606:             */
0607:            protected void bind(Element e) {
0608:                AbstractDocument doc = (AbstractDocument) e.getOwnerDocument();
0609:                if (doc != document) {
0610:                    XBLManager xm = doc.getXBLManager();
0611:                    if (xm instanceof  DefaultXBLManager) {
0612:                        ((DefaultXBLManager) xm).bind(e);
0613:                        return;
0614:                    }
0615:                }
0616:
0617:                if (e instanceof  BindableElement) {
0618:                    DefinitionRecord defRec = getActiveDefinition(e
0619:                            .getNamespaceURI(), e.getLocalName());
0620:                    setActiveDefinition((BindableElement) e, defRec);
0621:                } else {
0622:                    NodeList nl = getXblScopedChildNodes(e);
0623:                    for (int i = 0; i < nl.getLength(); i++) {
0624:                        Node n = nl.item(i);
0625:                        if (n.getNodeType() == Node.ELEMENT_NODE) {
0626:                            bind((Element) n);
0627:                        }
0628:                    }
0629:                }
0630:            }
0631:
0632:            /**
0633:             * Rebinds each bindable element of the given name in the given element's
0634:             * subtree.
0635:             */
0636:            protected void rebind(String namespaceURI, String localName,
0637:                    Element e) {
0638:                AbstractDocument doc = (AbstractDocument) e.getOwnerDocument();
0639:                if (doc != document) {
0640:                    XBLManager xm = doc.getXBLManager();
0641:                    if (xm instanceof  DefaultXBLManager) {
0642:                        ((DefaultXBLManager) xm).rebind(namespaceURI,
0643:                                localName, e);
0644:                        return;
0645:                    }
0646:                }
0647:
0648:                if (e instanceof  BindableElement
0649:                        && namespaceURI.equals(e.getNamespaceURI())
0650:                        && localName.equals(e.getLocalName())) {
0651:                    DefinitionRecord defRec = getActiveDefinition(e
0652:                            .getNamespaceURI(), e.getLocalName());
0653:                    setActiveDefinition((BindableElement) e, defRec);
0654:                } else {
0655:                    NodeList nl = getXblScopedChildNodes(e);
0656:                    for (int i = 0; i < nl.getLength(); i++) {
0657:                        Node n = nl.item(i);
0658:                        if (n.getNodeType() == Node.ELEMENT_NODE) {
0659:                            rebind(namespaceURI, localName, (Element) n);
0660:                        }
0661:                    }
0662:                }
0663:            }
0664:
0665:            /**
0666:             * Sets the given definition as the active one for a particular
0667:             * bindable element.
0668:             */
0669:            protected void setActiveDefinition(BindableElement elt,
0670:                    DefinitionRecord defRec) {
0671:                XBLRecord rec = getRecord(elt);
0672:                rec.definitionElement = defRec == null ? null
0673:                        : defRec.definition;
0674:                if (defRec != null && defRec.definition != null
0675:                        && defRec.template != null) {
0676:                    setXblShadowTree(elt, cloneTemplate(defRec.template));
0677:                } else {
0678:                    setXblShadowTree(elt, null);
0679:                }
0680:            }
0681:
0682:            /**
0683:             * Sets the shadow tree for the given bindable element.
0684:             */
0685:            protected void setXblShadowTree(BindableElement elt,
0686:                    XBLOMShadowTreeElement newShadow) {
0687:                XBLOMShadowTreeElement oldShadow = (XBLOMShadowTreeElement) getXblShadowTree(elt);
0688:                if (oldShadow != null) {
0689:                    fireShadowTreeEvent(elt, XBL_UNBINDING_EVENT_TYPE,
0690:                            oldShadow);
0691:                    ContentManager cm = getContentManager(oldShadow);
0692:                    if (cm != null) {
0693:                        cm.dispose();
0694:                    }
0695:                    elt.setShadowTree(null);
0696:                    XBLRecord rec = getRecord(oldShadow);
0697:                    rec.boundElement = null;
0698:                    oldShadow.removeEventListenerNS(
0699:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0700:                            "DOMSubtreeModified", docSubtreeListener, false);
0701:                }
0702:                if (newShadow != null) {
0703:                    newShadow.addEventListenerNS(
0704:                            XMLConstants.XML_EVENTS_NAMESPACE_URI,
0705:                            "DOMSubtreeModified", docSubtreeListener, false,
0706:                            null);
0707:                    fireShadowTreeEvent(elt, XBL_PREBIND_EVENT_TYPE, newShadow);
0708:                    elt.setShadowTree(newShadow);
0709:                    XBLRecord rec = getRecord(newShadow);
0710:                    rec.boundElement = elt;
0711:                    AbstractDocument doc = (AbstractDocument) elt
0712:                            .getOwnerDocument();
0713:                    XBLManager xm = doc.getXBLManager();
0714:                    ContentManager cm = new ContentManager(newShadow, xm);
0715:                    setContentManager(newShadow, cm);
0716:                }
0717:                invalidateChildNodes(elt);
0718:                if (newShadow != null) {
0719:                    NodeList nl = getXblScopedChildNodes(elt);
0720:                    for (int i = 0; i < nl.getLength(); i++) {
0721:                        Node n = nl.item(i);
0722:                        if (n.getNodeType() == Node.ELEMENT_NODE) {
0723:                            bind((Element) n);
0724:                        }
0725:                    }
0726:                    dispatchBindingChangedEvent(elt, newShadow);
0727:                    fireShadowTreeEvent(elt, XBL_BOUND_EVENT_TYPE, newShadow);
0728:                } else {
0729:                    dispatchBindingChangedEvent(elt, newShadow);
0730:                }
0731:            }
0732:
0733:            /**
0734:             * Fires a ShadowTreeEvent of the given type on this element.
0735:             */
0736:            protected void fireShadowTreeEvent(BindableElement elt,
0737:                    String type, XBLShadowTreeElement e) {
0738:                DocumentEvent de = (DocumentEvent) elt.getOwnerDocument();
0739:                ShadowTreeEvent evt = (ShadowTreeEvent) de
0740:                        .createEvent("ShadowTreeEvent");
0741:                evt.initShadowTreeEventNS(XBL_NAMESPACE_URI, type, true, false,
0742:                        e);
0743:                elt.dispatchEvent(evt);
0744:            }
0745:
0746:            /**
0747:             * Clones a template element for use as a shadow tree.
0748:             */
0749:            protected XBLOMShadowTreeElement cloneTemplate(
0750:                    XBLOMTemplateElement template) {
0751:                XBLOMShadowTreeElement clone = (XBLOMShadowTreeElement) template
0752:                        .getOwnerDocument().createElementNS(XBL_NAMESPACE_URI,
0753:                                XBL_SHADOW_TREE_TAG);
0754:                NamedNodeMap attrs = template.getAttributes();
0755:                for (int i = 0; i < attrs.getLength(); i++) {
0756:                    Attr attr = (Attr) attrs.item(i);
0757:                    if (attr instanceof  AbstractAttrNS) {
0758:                        clone.setAttributeNodeNS(attr);
0759:                    } else {
0760:                        clone.setAttributeNode(attr);
0761:                    }
0762:                }
0763:                for (Node n = template.getFirstChild(); n != null; n = n
0764:                        .getNextSibling()) {
0765:                    clone.appendChild(n.cloneNode(true));
0766:                }
0767:                return clone;
0768:            }
0769:
0770:            /**
0771:             * Get the parent of a node in the fully flattened tree.
0772:             */
0773:            public Node getXblParentNode(Node n) {
0774:                Node contentElement = getXblContentElement(n);
0775:                Node parent = contentElement == null ? n.getParentNode()
0776:                        : contentElement.getParentNode();
0777:                if (parent instanceof  XBLOMContentElement) {
0778:                    parent = parent.getParentNode();
0779:                }
0780:                if (parent instanceof  XBLOMShadowTreeElement) {
0781:                    parent = getXblBoundElement(parent);
0782:                }
0783:                return parent;
0784:            }
0785:
0786:            /**
0787:             * Get the list of child nodes of a node in the fully flattened tree.
0788:             */
0789:            public NodeList getXblChildNodes(Node n) {
0790:                XBLRecord rec = getRecord(n);
0791:                if (rec.childNodes == null) {
0792:                    rec.childNodes = new XblChildNodes(rec);
0793:                }
0794:                return rec.childNodes;
0795:            }
0796:
0797:            /**
0798:             * Get the list of child nodes of a node in the fully flattened tree
0799:             * that are within the same shadow scope.
0800:             */
0801:            public NodeList getXblScopedChildNodes(Node n) {
0802:                XBLRecord rec = getRecord(n);
0803:                if (rec.scopedChildNodes == null) {
0804:                    rec.scopedChildNodes = new XblScopedChildNodes(rec);
0805:                }
0806:                return rec.scopedChildNodes;
0807:            }
0808:
0809:            /**
0810:             * Get the first child node of a node in the fully flattened tree.
0811:             */
0812:            public Node getXblFirstChild(Node n) {
0813:                NodeList nl = getXblChildNodes(n);
0814:                return nl.item(0);
0815:            }
0816:
0817:            /**
0818:             * Get the last child node of a node in the fully flattened tree.
0819:             */
0820:            public Node getXblLastChild(Node n) {
0821:                NodeList nl = getXblChildNodes(n);
0822:                return nl.item(nl.getLength() - 1);
0823:            }
0824:
0825:            /**
0826:             * Get the node which directly precedes a node in the xblParentNode's
0827:             * xblChildNodes list.
0828:             */
0829:            public Node getXblPreviousSibling(Node n) {
0830:                Node p = getXblParentNode(n);
0831:                if (p == null || getRecord(p).childNodes == null) {
0832:                    return n.getPreviousSibling();
0833:                }
0834:                XBLRecord rec = getRecord(n);
0835:                if (!rec.linksValid) {
0836:                    updateLinks(n);
0837:                }
0838:                return rec.previousSibling;
0839:            }
0840:
0841:            /**
0842:             * Get the node which directly follows a node in the xblParentNode's
0843:             * xblChildNodes list.
0844:             */
0845:            public Node getXblNextSibling(Node n) {
0846:                Node p = getXblParentNode(n);
0847:                if (p == null || getRecord(p).childNodes == null) {
0848:                    return n.getNextSibling();
0849:                }
0850:                XBLRecord rec = getRecord(n);
0851:                if (!rec.linksValid) {
0852:                    updateLinks(n);
0853:                }
0854:                return rec.nextSibling;
0855:            }
0856:
0857:            /**
0858:             * Get the first element child of a node in the fully flattened tree.
0859:             */
0860:            public Element getXblFirstElementChild(Node n) {
0861:                n = getXblFirstChild(n);
0862:                while (n != null && n.getNodeType() != Node.ELEMENT_NODE) {
0863:                    n = getXblNextSibling(n);
0864:                }
0865:                return (Element) n;
0866:            }
0867:
0868:            /**
0869:             * Get the last element child of a node in the fully flattened tree.
0870:             */
0871:            public Element getXblLastElementChild(Node n) {
0872:                n = getXblLastChild(n);
0873:                while (n != null && n.getNodeType() != Node.ELEMENT_NODE) {
0874:                    n = getXblPreviousSibling(n);
0875:                }
0876:                return (Element) n;
0877:            }
0878:
0879:            /**
0880:             * Get the first element that precedes the a node in the
0881:             * xblParentNode's xblChildNodes list.
0882:             */
0883:            public Element getXblPreviousElementSibling(Node n) {
0884:                do {
0885:                    n = getXblPreviousSibling(n);
0886:                } while (n != null && n.getNodeType() != Node.ELEMENT_NODE);
0887:                return (Element) n;
0888:            }
0889:
0890:            /**
0891:             * Get the first element that follows a node in the
0892:             * xblParentNode's xblChildNodes list.
0893:             */
0894:            public Element getXblNextElementSibling(Node n) {
0895:                do {
0896:                    n = getXblNextSibling(n);
0897:                } while (n != null && n.getNodeType() != Node.ELEMENT_NODE);
0898:                return (Element) n;
0899:            }
0900:
0901:            /**
0902:             * Get the bound element whose shadow tree a node resides in.
0903:             */
0904:            public Element getXblBoundElement(Node n) {
0905:                while (n != null && !(n instanceof  XBLShadowTreeElement)) {
0906:                    XBLOMContentElement content = getXblContentElement(n);
0907:                    if (content != null) {
0908:                        n = content;
0909:                    }
0910:                    n = n.getParentNode();
0911:                }
0912:                if (n == null) {
0913:                    return null;
0914:                }
0915:                return getRecord(n).boundElement;
0916:            }
0917:
0918:            /**
0919:             * Get the shadow tree of a node.
0920:             */
0921:            public Element getXblShadowTree(Node n) {
0922:                if (n instanceof  BindableElement) {
0923:                    BindableElement elt = (BindableElement) n;
0924:                    return elt.getShadowTree();
0925:                }
0926:                return null;
0927:            }
0928:
0929:            /**
0930:             * Get the xbl:definition elements currently binding an element.
0931:             */
0932:            public NodeList getXblDefinitions(Node n) {
0933:                final String namespaceURI = n.getNamespaceURI();
0934:                final String localName = n.getLocalName();
0935:                return new NodeList() {
0936:                    public Node item(int i) {
0937:                        TreeSet defs = (TreeSet) definitionLists.get(
0938:                                namespaceURI, localName);
0939:                        if (defs != null && defs.size() != 0 && i == 0) {
0940:                            DefinitionRecord defRec = (DefinitionRecord) defs
0941:                                    .first();
0942:                            return defRec.definition;
0943:                        }
0944:                        return null;
0945:                    }
0946:
0947:                    public int getLength() {
0948:                        Set defs = (TreeSet) definitionLists.get(namespaceURI,
0949:                                localName);
0950:                        return defs != null && defs.size() != 0 ? 1 : 0;
0951:                    }
0952:                };
0953:            }
0954:
0955:            /**
0956:             * Returns the XBL record for the given node.
0957:             */
0958:            protected XBLRecord getRecord(Node n) {
0959:                XBLManagerData xmd = (XBLManagerData) n;
0960:                XBLRecord rec = (XBLRecord) xmd.getManagerData();
0961:                if (rec == null) {
0962:                    rec = new XBLRecord();
0963:                    rec.node = n;
0964:                    xmd.setManagerData(rec);
0965:                }
0966:                return rec;
0967:            }
0968:
0969:            /**
0970:             * Updates the xblPreviousSibling and xblNextSibling properties of the
0971:             * given XBL node.
0972:             */
0973:            protected void updateLinks(Node n) {
0974:                XBLRecord rec = getRecord(n);
0975:                rec.previousSibling = null;
0976:                rec.nextSibling = null;
0977:                rec.linksValid = true;
0978:                Node p = getXblParentNode(n);
0979:                if (p != null) {
0980:                    NodeList xcn = getXblChildNodes(p);
0981:                    if (xcn instanceof  XblChildNodes) {
0982:                        ((XblChildNodes) xcn).update();
0983:                    }
0984:                }
0985:            }
0986:
0987:            /**
0988:             * Returns the content element that caused the given node to be
0989:             * present in the flattened tree.
0990:             */
0991:            public XBLOMContentElement getXblContentElement(Node n) {
0992:                return getRecord(n).contentElement;
0993:            }
0994:
0995:            /**
0996:             * Determines the number of nodes events should bubble if the
0997:             * mouse pointer has moved from one element to another.
0998:             * @param from the element from which the mouse pointer moved
0999:             * @param to   the element to which the mouse pointer moved
1000:             */
1001:            public static int computeBubbleLimit(Node from, Node to) {
1002:                ArrayList fromList = new ArrayList(10);
1003:                ArrayList toList = new ArrayList(10);
1004:                while (from != null) {
1005:                    fromList.add(from);
1006:                    from = ((NodeXBL) from).getXblParentNode();
1007:                }
1008:                while (to != null) {
1009:                    toList.add(to);
1010:                    to = ((NodeXBL) to).getXblParentNode();
1011:                }
1012:                int fromSize = fromList.size();
1013:                int toSize = toList.size();
1014:                for (int i = 0; i < fromSize && i < toSize; i++) {
1015:                    Node n1 = (Node) fromList.get(fromSize - i - 1);
1016:                    Node n2 = (Node) toList.get(toSize - i - 1);
1017:                    if (n1 != n2) {
1018:                        Node prevBoundElement = ((NodeXBL) n1)
1019:                                .getXblBoundElement();
1020:                        while (i > 0
1021:                                && prevBoundElement != fromList.get(fromSize
1022:                                        - i - 1)) {
1023:                            i--;
1024:                        }
1025:                        return fromSize - i - 1;
1026:                    }
1027:                }
1028:                return 1;
1029:            }
1030:
1031:            /**
1032:             * Returns the ContentManager that handles the shadow tree the given
1033:             * node resides in.
1034:             */
1035:            public ContentManager getContentManager(Node n) {
1036:                Node b = getXblBoundElement(n);
1037:                if (b != null) {
1038:                    Element s = getXblShadowTree(b);
1039:                    if (s != null) {
1040:                        ContentManager cm;
1041:                        Document doc = b.getOwnerDocument();
1042:                        if (doc != document) {
1043:                            DefaultXBLManager xm = (DefaultXBLManager) ((AbstractDocument) doc)
1044:                                    .getXBLManager();
1045:                            cm = (ContentManager) xm.contentManagers.get(s);
1046:                        } else {
1047:                            cm = (ContentManager) contentManagers.get(s);
1048:                        }
1049:                        return cm;
1050:                    }
1051:                }
1052:                return null;
1053:            }
1054:
1055:            /**
1056:             * Records the ContentManager that handles the given shadow tree.
1057:             */
1058:            void setContentManager(Element shadow, ContentManager cm) {
1059:                if (cm == null) {
1060:                    contentManagers.remove(shadow);
1061:                } else {
1062:                    contentManagers.put(shadow, cm);
1063:                }
1064:            }
1065:
1066:            /**
1067:             * Mark the xblChildNodes and xblScopedChildNodes variables
1068:             * as invalid.
1069:             */
1070:            public void invalidateChildNodes(Node n) {
1071:                XBLRecord rec = getRecord(n);
1072:                if (rec.childNodes != null) {
1073:                    rec.childNodes.invalidate();
1074:                }
1075:                if (rec.scopedChildNodes != null) {
1076:                    rec.scopedChildNodes.invalidate();
1077:                }
1078:            }
1079:
1080:            /**
1081:             * Adds the specified ContentSelectionChangedListener to the
1082:             * global listener list.
1083:             */
1084:            public void addContentSelectionChangedListener(
1085:                    ContentSelectionChangedListener l) {
1086:                contentSelectionChangedListenerList.add(
1087:                        ContentSelectionChangedListener.class, l);
1088:            }
1089:
1090:            /**
1091:             * Removes the specified ContentSelectionChangedListener from the
1092:             * global listener list.
1093:             */
1094:            public void removeContentSelectionChangedListener(
1095:                    ContentSelectionChangedListener l) {
1096:                contentSelectionChangedListenerList.remove(
1097:                        ContentSelectionChangedListener.class, l);
1098:            }
1099:
1100:            /**
1101:             * Returns an array of the gloabl ContentSelectionChangedListeners.
1102:             */
1103:            protected Object[] getContentSelectionChangedListeners() {
1104:                return contentSelectionChangedListenerList.getListenerList();
1105:            }
1106:
1107:            /**
1108:             * Called by the ContentManager of a shadow tree to indicate some
1109:             * selected nodes have changed.
1110:             */
1111:            void shadowTreeSelectedContentChanged(Set deselected, Set selected) {
1112:                Iterator i = deselected.iterator();
1113:                while (i.hasNext()) {
1114:                    Node n = (Node) i.next();
1115:                    if (n.getNodeType() == Node.ELEMENT_NODE) {
1116:                        unbind((Element) n);
1117:                    }
1118:                }
1119:                i = selected.iterator();
1120:                while (i.hasNext()) {
1121:                    Node n = (Node) i.next();
1122:                    if (n.getNodeType() == Node.ELEMENT_NODE) {
1123:                        bind((Element) n);
1124:                    }
1125:                }
1126:            }
1127:
1128:            /**
1129:             * Adds the specified BindingListener to the global listener list.
1130:             */
1131:            public void addBindingListener(BindingListener l) {
1132:                bindingListenerList.add(BindingListener.class, l);
1133:            }
1134:
1135:            /**
1136:             * Removes the specified BindingListener from the global listener list.
1137:             */
1138:            public void removeBindingListener(BindingListener l) {
1139:                bindingListenerList.remove(BindingListener.class, l);
1140:            }
1141:
1142:            /**
1143:             * Dispatches a BindingEvent the registered listeners.
1144:             * @param bindableElement the bindable element whose binding has changed
1145:             * @param shadowTree the new shadow tree of the bindable element
1146:             */
1147:            protected void dispatchBindingChangedEvent(Element bindableElement,
1148:                    Element shadowTree) {
1149:                Object[] ls = bindingListenerList.getListenerList();
1150:                for (int i = ls.length - 2; i >= 0; i -= 2) {
1151:                    BindingListener l = (BindingListener) ls[i + 1];
1152:                    l.bindingChanged(bindableElement, shadowTree);
1153:                }
1154:            }
1155:
1156:            /**
1157:             * Returns whether the given definition element is the active one
1158:             * for its element name.
1159:             */
1160:            protected boolean isActiveDefinition(XBLOMDefinitionElement def,
1161:                    Element imp) {
1162:                DefinitionRecord defRec = (DefinitionRecord) definitions.get(
1163:                        def, imp);
1164:                if (defRec == null) {
1165:                    return false;
1166:                }
1167:                return defRec == getActiveDefinition(defRec.namespaceURI,
1168:                        defRec.localName);
1169:            }
1170:
1171:            /**
1172:             * Record class for storing information about an XBL definition.
1173:             */
1174:            protected class DefinitionRecord implements  Comparable {
1175:
1176:                /**
1177:                 * The namespace URI.
1178:                 */
1179:                public String namespaceURI;
1180:
1181:                /**
1182:                 * The local name.
1183:                 */
1184:                public String localName;
1185:
1186:                /**
1187:                 * The definition element.
1188:                 */
1189:                public XBLOMDefinitionElement definition;
1190:
1191:                /**
1192:                 * The template element for this definition.
1193:                 */
1194:                public XBLOMTemplateElement template;
1195:
1196:                /**
1197:                 * The import element that imported this definition.
1198:                 */
1199:                public Element importElement;
1200:
1201:                /**
1202:                 * Creates a new DefinitionRecord.
1203:                 */
1204:                public DefinitionRecord(String ns, String ln,
1205:                        XBLOMDefinitionElement def, XBLOMTemplateElement t,
1206:                        Element imp) {
1207:                    namespaceURI = ns;
1208:                    localName = ln;
1209:                    definition = def;
1210:                    template = t;
1211:                    importElement = imp;
1212:                }
1213:
1214:                /**
1215:                 * Returns whether two definition records are the same.
1216:                 */
1217:                public boolean equals(Object other) {
1218:                    return compareTo(other) == 0;
1219:                }
1220:
1221:                /**
1222:                 * Compares two definition records.
1223:                 */
1224:                public int compareTo(Object other) {
1225:                    DefinitionRecord rec = (DefinitionRecord) other;
1226:                    AbstractNode n1, n2;
1227:                    if (importElement == null) {
1228:                        n1 = definition;
1229:                        if (rec.importElement == null) {
1230:                            n2 = rec.definition;
1231:                        } else {
1232:                            n2 = (AbstractNode) rec.importElement;
1233:                        }
1234:                    } else if (rec.importElement == null) {
1235:                        n1 = (AbstractNode) importElement;
1236:                        n2 = rec.definition;
1237:                    } else if (definition.getOwnerDocument() == rec.definition
1238:                            .getOwnerDocument()) {
1239:                        n1 = definition;
1240:                        n2 = rec.definition;
1241:                    } else {
1242:                        n1 = (AbstractNode) importElement;
1243:                        n2 = (AbstractNode) rec.importElement;
1244:                    }
1245:                    short comp = n1.compareDocumentPosition(n2);
1246:                    if ((comp & AbstractNode.DOCUMENT_POSITION_PRECEDING) != 0) {
1247:                        return -1;
1248:                    }
1249:                    if ((comp & AbstractNode.DOCUMENT_POSITION_FOLLOWING) != 0) {
1250:                        return 1;
1251:                    }
1252:                    return 0;
1253:                }
1254:            }
1255:
1256:            /**
1257:             * Record class for storing information about an XBL import.
1258:             */
1259:            protected class ImportRecord {
1260:
1261:                /**
1262:                 * The import element.
1263:                 */
1264:                public Element importElement;
1265:
1266:                /**
1267:                 * The imported tree.
1268:                 */
1269:                public Node node;
1270:
1271:                /**
1272:                 * The DOM node inserted listener for definitions accessed through
1273:                 * this import.
1274:                 */
1275:                public DefNodeInsertedListener defNodeInsertedListener;
1276:
1277:                /**
1278:                 * The DOM node removed listener for definitions accessed through
1279:                 * this import.
1280:                 */
1281:                public DefNodeRemovedListener defNodeRemovedListener;
1282:
1283:                /**
1284:                 * The DOM attribute mutation listener for definitions accessed through
1285:                 * this import.
1286:                 */
1287:                public DefAttrListener defAttrListener;
1288:
1289:                /**
1290:                 * The DOM node inserted listener for the imported tree.
1291:                 */
1292:                public ImportInsertedListener importInsertedListener;
1293:
1294:                /**
1295:                 * The DOM node removed listener for the imported tree.
1296:                 */
1297:                public ImportRemovedListener importRemovedListener;
1298:
1299:                /**
1300:                 * The DOM subtree modified listener for the imported tree.
1301:                 */
1302:                public ImportSubtreeListener importSubtreeListener;
1303:
1304:                /**
1305:                 * The DOM subtree modified listener for templates of definitions
1306:                 * accessed through this import.
1307:                 */
1308:                public TemplateMutationListener templateMutationListener;
1309:
1310:                /**
1311:                 * Creates a new ImportRecord.
1312:                 */
1313:                public ImportRecord(Element imp, Node n) {
1314:                    importElement = imp;
1315:                    node = n;
1316:                    defNodeInsertedListener = new DefNodeInsertedListener(imp);
1317:                    defNodeRemovedListener = new DefNodeRemovedListener(imp);
1318:                    defAttrListener = new DefAttrListener(imp);
1319:                    importInsertedListener = new ImportInsertedListener(imp);
1320:                    importRemovedListener = new ImportRemovedListener();
1321:                    importSubtreeListener = new ImportSubtreeListener(imp,
1322:                            importRemovedListener);
1323:                    templateMutationListener = new TemplateMutationListener(imp);
1324:                }
1325:            }
1326:
1327:            /**
1328:             * DOM node inserted listener for imported XBL trees.
1329:             */
1330:            protected class ImportInsertedListener implements  EventListener {
1331:
1332:                /**
1333:                 * The import element.
1334:                 */
1335:                protected Element importElement;
1336:
1337:                /**
1338:                 * Creates a new ImportInsertedListener.
1339:                 */
1340:                public ImportInsertedListener(Element importElement) {
1341:                    this .importElement = importElement;
1342:                }
1343:
1344:                /**
1345:                 * Handles the event.
1346:                 */
1347:                public void handleEvent(Event evt) {
1348:                    EventTarget target = evt.getTarget();
1349:                    if (target instanceof  XBLOMDefinitionElement) {
1350:                        XBLOMDefinitionElement def = (XBLOMDefinitionElement) target;
1351:                        addDefinition(def.getElementNamespaceURI(), def
1352:                                .getElementLocalName(), def, importElement);
1353:                    }
1354:                }
1355:            }
1356:
1357:            /**
1358:             * DOM node removed listener for imported XBL trees.
1359:             */
1360:            protected class ImportRemovedListener implements  EventListener {
1361:
1362:                /**
1363:                 * List of definition elements to be removed from the document.
1364:                 */
1365:                protected LinkedList toBeRemoved = new LinkedList();
1366:
1367:                /**
1368:                 * Handles the event.
1369:                 */
1370:                public void handleEvent(Event evt) {
1371:                    toBeRemoved.add(evt.getTarget());
1372:                }
1373:            }
1374:
1375:            /**
1376:             * DOM subtree listener for imported XBL trees.
1377:             */
1378:            protected class ImportSubtreeListener implements  EventListener {
1379:
1380:                /**
1381:                 * The import element.
1382:                 */
1383:                protected Element importElement;
1384:
1385:                /**
1386:                 * The ImportedRemovedListener to check for to-be-removed definitions.
1387:                 */
1388:                protected ImportRemovedListener importRemovedListener;
1389:
1390:                /**
1391:                 * Creates a new ImportSubtreeListener.
1392:                 */
1393:                public ImportSubtreeListener(Element imp,
1394:                        ImportRemovedListener irl) {
1395:                    importElement = imp;
1396:                    importRemovedListener = irl;
1397:                }
1398:
1399:                /**
1400:                 * Handles the event.
1401:                 */
1402:                public void handleEvent(Event evt) {
1403:                    Object[] defs = importRemovedListener.toBeRemoved.toArray();
1404:                    importRemovedListener.toBeRemoved.clear();
1405:                    for (int i = 0; i < defs.length; i++) {
1406:                        XBLOMDefinitionElement def = (XBLOMDefinitionElement) defs[i];
1407:                        DefinitionRecord defRec = (DefinitionRecord) definitions
1408:                                .get(def, importElement);
1409:                        removeDefinition(defRec);
1410:                    }
1411:                }
1412:            }
1413:
1414:            /**
1415:             * DOM node inserted listener for the document.
1416:             */
1417:            protected class DocInsertedListener implements  EventListener {
1418:
1419:                /**
1420:                 * Handles the event.
1421:                 */
1422:                public void handleEvent(Event evt) {
1423:                    EventTarget target = evt.getTarget();
1424:                    if (target instanceof  XBLOMDefinitionElement) {
1425:                        // only handle definition elements in document-level scope
1426:                        if (getXblBoundElement((Node) target) == null) { // ??? suspect cast ???
1427:                            XBLOMDefinitionElement def = (XBLOMDefinitionElement) target;
1428:                            if (def.getAttributeNS(null, XBL_REF_ATTRIBUTE)
1429:                                    .length() == 0) {
1430:                                addDefinition(def.getElementNamespaceURI(), def
1431:                                        .getElementLocalName(), def, null);
1432:                            } else {
1433:                                addDefinitionRef(def);
1434:                            }
1435:                        }
1436:                    } else if (target instanceof  XBLOMImportElement) {
1437:                        // only handle import elements in document-level scope
1438:                        if (getXblBoundElement((Node) target) == null) { // ??? suspect cast ???
1439:                            addImport((Element) target);
1440:                        }
1441:                    } else {
1442:                        evt = XBLEventSupport.getUltimateOriginalEvent(evt);
1443:                        target = evt.getTarget();
1444:                        Node parent = getXblParentNode((Node) target);
1445:                        if (parent != null) {
1446:                            invalidateChildNodes(parent);
1447:                        }
1448:                        if (target instanceof  BindableElement) {
1449:                            // Only bind it if it's not the descendent of a bound
1450:                            // element.  If it is, and this new element will be
1451:                            // selected by an xbl:content element in the shadow tree,
1452:                            // the ContentManager will bind it.
1453:                            for (Node n = ((Node) target).getParentNode(); n != null; n = n
1454:                                    .getParentNode()) {
1455:                                if (n instanceof  BindableElement
1456:                                        && getRecord(n).definitionElement != null) {
1457:                                    return;
1458:                                }
1459:                            }
1460:                            bind((Element) target);
1461:                        }
1462:                    }
1463:                }
1464:            }
1465:
1466:            /**
1467:             * DOM node removed listener for the document.
1468:             */
1469:            protected class DocRemovedListener implements  EventListener {
1470:
1471:                /**
1472:                 * List of definition elements to be removed from the document.
1473:                 */
1474:                protected LinkedList defsToBeRemoved = new LinkedList();
1475:
1476:                /**
1477:                 * List of import elements to be removed from the document.
1478:                 */
1479:                protected LinkedList importsToBeRemoved = new LinkedList();
1480:
1481:                /**
1482:                 * List of nodes to have their XBL child lists invalidated.
1483:                 */
1484:                protected LinkedList nodesToBeInvalidated = new LinkedList();
1485:
1486:                /**
1487:                 * Handles the event.
1488:                 */
1489:                public void handleEvent(Event evt) {
1490:                    EventTarget target = evt.getTarget();
1491:                    if (target instanceof  XBLOMDefinitionElement) {
1492:                        // only handle definition elements in document-level scope
1493:                        if (getXblBoundElement((Node) target) == null) {
1494:                            defsToBeRemoved.add(target);
1495:                        }
1496:                    } else if (target instanceof  XBLOMImportElement) {
1497:                        // only handle import elements in document-level scope
1498:                        if (getXblBoundElement((Node) target) == null) {
1499:                            importsToBeRemoved.add(target);
1500:                        }
1501:                    }
1502:
1503:                    Node parent = getXblParentNode((Node) target);
1504:                    if (parent != null) {
1505:                        nodesToBeInvalidated.add(parent);
1506:                    }
1507:                }
1508:            }
1509:
1510:            /**
1511:             * DOM subtree mutation listener for the document.
1512:             */
1513:            protected class DocSubtreeListener implements  EventListener {
1514:
1515:                /**
1516:                 * Handles the event.
1517:                 */
1518:                public void handleEvent(Event evt) {
1519:                    Object[] defs = docRemovedListener.defsToBeRemoved
1520:                            .toArray();
1521:                    docRemovedListener.defsToBeRemoved.clear();
1522:                    for (int i = 0; i < defs.length; i++) {
1523:                        XBLOMDefinitionElement def = (XBLOMDefinitionElement) defs[i];
1524:                        if (def.getAttributeNS(null, XBL_REF_ATTRIBUTE)
1525:                                .length() == 0) {
1526:                            DefinitionRecord defRec = (DefinitionRecord) definitions
1527:                                    .get(def, null);
1528:                            removeDefinition(defRec);
1529:                        } else {
1530:                            removeDefinitionRef(def);
1531:                        }
1532:                    }
1533:
1534:                    Object[] imps = docRemovedListener.importsToBeRemoved
1535:                            .toArray();
1536:                    docRemovedListener.importsToBeRemoved.clear();
1537:                    for (int i = 0; i < imps.length; i++) {
1538:                        removeImport((Element) imps[i]);
1539:                    }
1540:
1541:                    Object[] nodes = docRemovedListener.nodesToBeInvalidated
1542:                            .toArray();
1543:                    docRemovedListener.nodesToBeInvalidated.clear();
1544:                    for (int i = 0; i < nodes.length; i++) {
1545:                        invalidateChildNodes((Node) nodes[i]);
1546:                    }
1547:                }
1548:            }
1549:
1550:            /**
1551:             * DOM mutation listener for template elements.
1552:             */
1553:            protected class TemplateMutationListener implements  EventListener {
1554:
1555:                /**
1556:                 * The import element.
1557:                 */
1558:                protected Element importElement;
1559:
1560:                /**
1561:                 * Creates a new TemplateMutationListener.
1562:                 */
1563:                public TemplateMutationListener(Element imp) {
1564:                    importElement = imp;
1565:                }
1566:
1567:                /**
1568:                 * Handles the event.
1569:                 */
1570:                public void handleEvent(Event evt) {
1571:                    Node n = (Node) evt.getTarget();
1572:                    while (n != null && !(n instanceof  XBLOMDefinitionElement)) {
1573:                        n = n.getParentNode();
1574:                    }
1575:
1576:                    DefinitionRecord defRec = (DefinitionRecord) definitions
1577:                            .get(n, importElement);
1578:                    if (defRec == null) {
1579:                        return;
1580:                    }
1581:
1582:                    rebind(defRec.namespaceURI, defRec.localName, document
1583:                            .getDocumentElement());
1584:                }
1585:            }
1586:
1587:            /**
1588:             * DOM attribute mutation listener for definition elements.
1589:             */
1590:            protected class DefAttrListener implements  EventListener {
1591:
1592:                /**
1593:                 * The import element.
1594:                 */
1595:                protected Element importElement;
1596:
1597:                /**
1598:                 * Creates a new DefAttrListener.
1599:                 */
1600:                public DefAttrListener(Element imp) {
1601:                    importElement = imp;
1602:                }
1603:
1604:                /**
1605:                 * Handles the event.
1606:                 */
1607:                public void handleEvent(Event evt) {
1608:                    EventTarget target = evt.getTarget();
1609:                    if (!(target instanceof  XBLOMDefinitionElement)) {
1610:                        return;
1611:                    }
1612:
1613:                    XBLOMDefinitionElement def = (XBLOMDefinitionElement) target;
1614:                    if (!isActiveDefinition(def, importElement)) {
1615:                        return;
1616:                    }
1617:
1618:                    MutationEvent mevt = (MutationEvent) evt;
1619:                    String attrName = mevt.getAttrName();
1620:                    if (attrName.equals(XBL_ELEMENT_ATTRIBUTE)) {
1621:                        DefinitionRecord defRec = (DefinitionRecord) definitions
1622:                                .get(def, importElement);
1623:                        removeDefinition(defRec);
1624:
1625:                        addDefinition(def.getElementNamespaceURI(), def
1626:                                .getElementLocalName(), def, importElement);
1627:                    } else if (attrName.equals(XBL_REF_ATTRIBUTE)) {
1628:                        if (mevt.getNewValue().length() != 0) {
1629:                            DefinitionRecord defRec = (DefinitionRecord) definitions
1630:                                    .get(def, importElement);
1631:                            removeDefinition(defRec);
1632:                            addDefinitionRef(def);
1633:                        }
1634:                    }
1635:                }
1636:            }
1637:
1638:            /**
1639:             * DOM node inserted listener for definition elements.
1640:             */
1641:            protected class DefNodeInsertedListener implements  EventListener {
1642:
1643:                /**
1644:                 * The import element.
1645:                 */
1646:                protected Element importElement;
1647:
1648:                /**
1649:                 * Creates a new DefNodeInsertedListener.
1650:                 */
1651:                public DefNodeInsertedListener(Element imp) {
1652:                    importElement = imp;
1653:                }
1654:
1655:                /**
1656:                 * Handles the event.
1657:                 */
1658:                public void handleEvent(Event evt) {
1659:                    MutationEvent mevt = (MutationEvent) evt;
1660:                    Node parent = mevt.getRelatedNode();
1661:                    if (!(parent instanceof  XBLOMDefinitionElement)) {
1662:                        return;
1663:                    }
1664:
1665:                    EventTarget target = evt.getTarget();
1666:                    if (!(target instanceof  XBLOMTemplateElement)) {
1667:                        return;
1668:                    }
1669:                    XBLOMTemplateElement template = (XBLOMTemplateElement) target;
1670:
1671:                    DefinitionRecord defRec = (DefinitionRecord) definitions
1672:                            .get(parent, importElement);
1673:                    if (defRec == null) {
1674:                        return;
1675:                    }
1676:
1677:                    ImportRecord ir = (ImportRecord) imports.get(importElement);
1678:
1679:                    if (defRec.template != null) {
1680:                        for (Node n = parent.getFirstChild(); n != null; n = n
1681:                                .getNextSibling()) {
1682:                            if (n == template) {
1683:                                removeTemplateElementListeners(defRec.template,
1684:                                        ir);
1685:                                defRec.template = template;
1686:                                break;
1687:                            } else if (n == defRec.template) {
1688:                                return;
1689:                            }
1690:                        }
1691:                    } else {
1692:                        defRec.template = template;
1693:                    }
1694:                    addTemplateElementListeners(template, ir);
1695:                    rebind(defRec.namespaceURI, defRec.localName, document
1696:                            .getDocumentElement());
1697:                }
1698:            }
1699:
1700:            /**
1701:             * DOM node removed listener for definition elements.
1702:             */
1703:            protected class DefNodeRemovedListener implements  EventListener {
1704:
1705:                /**
1706:                 * The import element.
1707:                 */
1708:                protected Element importElement;
1709:
1710:                /**
1711:                 * Creates a new DefNodeRemovedListener.
1712:                 */
1713:                public DefNodeRemovedListener(Element imp) {
1714:                    importElement = imp;
1715:                }
1716:
1717:                /**
1718:                 * Handles the event.
1719:                 */
1720:                public void handleEvent(Event evt) {
1721:                    MutationEvent mevt = (MutationEvent) evt;
1722:                    Node parent = mevt.getRelatedNode();
1723:                    if (!(parent instanceof  XBLOMDefinitionElement)) {
1724:                        return;
1725:                    }
1726:
1727:                    EventTarget target = evt.getTarget();
1728:                    if (!(target instanceof  XBLOMTemplateElement)) {
1729:                        return;
1730:                    }
1731:                    XBLOMTemplateElement template = (XBLOMTemplateElement) target;
1732:
1733:                    DefinitionRecord defRec = (DefinitionRecord) definitions
1734:                            .get(parent, importElement);
1735:                    if (defRec == null || defRec.template != template) {
1736:                        return;
1737:                    }
1738:
1739:                    ImportRecord ir = (ImportRecord) imports.get(importElement);
1740:
1741:                    removeTemplateElementListeners(template, ir);
1742:                    defRec.template = null;
1743:
1744:                    for (Node n = template.getNextSibling(); n != null; n = n
1745:                            .getNextSibling()) {
1746:                        if (n instanceof  XBLOMTemplateElement) {
1747:                            defRec.template = (XBLOMTemplateElement) n;
1748:                            break;
1749:                        }
1750:                    }
1751:
1752:                    addTemplateElementListeners(defRec.template, ir);
1753:                    rebind(defRec.namespaceURI, defRec.localName, document
1754:                            .getDocumentElement());
1755:                }
1756:            }
1757:
1758:            /**
1759:             * DOM attribute mutation listener for import elements.
1760:             */
1761:            protected class ImportAttrListener implements  EventListener {
1762:
1763:                /**
1764:                 * Handles the event.
1765:                 */
1766:                public void handleEvent(Event evt) {
1767:                    EventTarget target = evt.getTarget();
1768:                    if (target != evt.getCurrentTarget()) {
1769:                        return;
1770:                    }
1771:
1772:                    MutationEvent mevt = (MutationEvent) evt;
1773:                    if (mevt.getAttrName().equals(XBL_BINDINGS_ATTRIBUTE)) {
1774:                        Element imp = (Element) target;
1775:                        removeImport(imp);
1776:                        addImport(imp);
1777:                    }
1778:                }
1779:            }
1780:
1781:            /**
1782:             * DOM attribute mutation listener for referencing definition elements.
1783:             */
1784:            protected class RefAttrListener implements  EventListener {
1785:
1786:                /**
1787:                 * Handles the event.
1788:                 */
1789:                public void handleEvent(Event evt) {
1790:                    EventTarget target = evt.getTarget();
1791:                    if (target != evt.getCurrentTarget()) {
1792:                        return;
1793:                    }
1794:
1795:                    MutationEvent mevt = (MutationEvent) evt;
1796:                    if (mevt.getAttrName().equals(XBL_REF_ATTRIBUTE)) {
1797:                        Element defRef = (Element) target;
1798:                        removeDefinitionRef(defRef);
1799:                        if (mevt.getNewValue().length() == 0) {
1800:                            XBLOMDefinitionElement def = (XBLOMDefinitionElement) defRef;
1801:                            String ns = def.getElementNamespaceURI();
1802:                            String ln = def.getElementLocalName();
1803:                            addDefinition(ns, ln,
1804:                                    (XBLOMDefinitionElement) defRef, null);
1805:                        } else {
1806:                            addDefinitionRef(defRef);
1807:                        }
1808:                    }
1809:                }
1810:            }
1811:
1812:            /**
1813:             * XBL record.
1814:             */
1815:            protected class XBLRecord {
1816:
1817:                /**
1818:                 * The node.
1819:                 */
1820:                public Node node;
1821:
1822:                /**
1823:                 * The xblChildNodes NodeList for this node.
1824:                 */
1825:                public XblChildNodes childNodes;
1826:
1827:                /**
1828:                 * The xblScopedChildNodes NodeList for this node.
1829:                 */
1830:                public XblScopedChildNodes scopedChildNodes;
1831:
1832:                /**
1833:                 * The content element which caused this node to appear in the
1834:                 * flattened tree.
1835:                 */
1836:                public XBLOMContentElement contentElement;
1837:
1838:                /**
1839:                 * The definition element that applies to this element.
1840:                 */
1841:                public XBLOMDefinitionElement definitionElement;
1842:
1843:                /**
1844:                 * The bound element that owns this shadow tree, if this node
1845:                 * is an XBLOMShadowTreeElement.
1846:                 */
1847:                public BindableElement boundElement;
1848:
1849:                /**
1850:                 * Whether the next/previous links are valid.
1851:                 */
1852:                public boolean linksValid;
1853:
1854:                /**
1855:                 * The following sibling in the flattened tree.
1856:                 */
1857:                public Node nextSibling;
1858:
1859:                /**
1860:                 * The previous sibling in the flattened tree.
1861:                 */
1862:                public Node previousSibling;
1863:            }
1864:
1865:            /**
1866:             * To iterate over the XBL child nodes.
1867:             */
1868:            protected class XblChildNodes implements  NodeList {
1869:
1870:                /**
1871:                 * The XBLRecord.
1872:                 */
1873:                protected XBLRecord record;
1874:
1875:                /**
1876:                 * The nodes.
1877:                 */
1878:                protected List nodes;
1879:
1880:                /**
1881:                 * The number of nodes.
1882:                 */
1883:                protected int size;
1884:
1885:                /**
1886:                 * Creates a new XblChildNodes.
1887:                 */
1888:                public XblChildNodes(XBLRecord rec) {
1889:                    record = rec;
1890:                    nodes = new ArrayList();
1891:                    size = -1;
1892:                }
1893:
1894:                /**
1895:                 * Update the NodeList.
1896:                 */
1897:                protected void update() {
1898:                    size = 0;
1899:                    Node shadowTree = getXblShadowTree(record.node);
1900:                    Node last = null;
1901:                    Node m = shadowTree == null ? record.node.getFirstChild()
1902:                            : shadowTree.getFirstChild();
1903:                    while (m != null) {
1904:                        last = collectXblChildNodes(m, last);
1905:                        m = m.getNextSibling();
1906:                    }
1907:                    if (last != null) {
1908:                        XBLRecord rec = getRecord(last);
1909:                        rec.nextSibling = null;
1910:                        rec.linksValid = true;
1911:                    }
1912:                }
1913:
1914:                /**
1915:                 * Find the XBL child nodes of this element.
1916:                 */
1917:                protected Node collectXblChildNodes(Node n, Node prev) {
1918:                    boolean isChild = false;
1919:                    if (n.getNodeType() == Node.ELEMENT_NODE) {
1920:                        if (!XBL_NAMESPACE_URI.equals(n.getNamespaceURI())) {
1921:                            isChild = true;
1922:                        } else if (n instanceof  XBLOMContentElement) {
1923:                            ContentManager cm = getContentManager(n);
1924:                            if (cm != null) {
1925:                                NodeList selected = cm
1926:                                        .getSelectedContent((XBLOMContentElement) n);
1927:                                for (int i = 0; i < selected.getLength(); i++) {
1928:                                    prev = collectXblChildNodes(selected
1929:                                            .item(i), prev);
1930:                                }
1931:                            }
1932:                        }
1933:                    } else {
1934:                        isChild = true;
1935:                    }
1936:                    if (isChild) {
1937:                        nodes.add(n);
1938:                        size++;
1939:                        if (prev != null) {
1940:                            XBLRecord rec = getRecord(prev);
1941:                            rec.nextSibling = n;
1942:                            rec.linksValid = true;
1943:                        }
1944:                        XBLRecord rec = getRecord(n);
1945:                        rec.previousSibling = prev;
1946:                        rec.linksValid = true;
1947:                        prev = n;
1948:                    }
1949:                    return prev;
1950:                }
1951:
1952:                /**
1953:                 * Mark the xblNextSibling and xblPreviousSibling variables
1954:                 * on each node in the list as invalid, then invalidate the
1955:                 * NodeList.
1956:                 */
1957:                public void invalidate() {
1958:                    for (int i = 0; i < size; i++) {
1959:                        XBLRecord rec = getRecord((Node) nodes.get(i));
1960:                        rec.previousSibling = null;
1961:                        rec.nextSibling = null;
1962:                        rec.linksValid = false;
1963:                    }
1964:                    nodes.clear();
1965:                    size = -1;
1966:                }
1967:
1968:                /**
1969:                 * Returns the first node in the list.
1970:                 */
1971:                public Node getFirstNode() {
1972:                    if (size == -1) {
1973:                        update();
1974:                    }
1975:                    return size == 0 ? null : (Node) nodes.get(0);
1976:                }
1977:
1978:                /**
1979:                 * Returns the last node in the list.
1980:                 */
1981:                public Node getLastNode() {
1982:                    if (size == -1) {
1983:                        update();
1984:                    }
1985:                    return size == 0 ? null : (Node) nodes
1986:                            .get(nodes.size() - 1);
1987:                }
1988:
1989:                /**
1990:                 * <b>DOM</b>: Implements {@link org.w3c.dom.NodeList#item(int)}.
1991:                 */
1992:                public Node item(int index) {
1993:                    if (size == -1) {
1994:                        update();
1995:                    }
1996:                    if (index < 0 || index >= size) {
1997:                        return null;
1998:                    }
1999:                    return (Node) nodes.get(index);
2000:                }
2001:
2002:                /**
2003:                 * <b>DOM</b>: Implements {@link org.w3c.dom.NodeList#getLength()}.
2004:                 */
2005:                public int getLength() {
2006:                    if (size == -1) {
2007:                        update();
2008:                    }
2009:                    return size;
2010:                }
2011:            }
2012:
2013:            /**
2014:             * To iterate over the scoped XBL child nodes.
2015:             */
2016:            protected class XblScopedChildNodes extends XblChildNodes {
2017:
2018:                /**
2019:                 * Creates a new XblScopedChildNodes object.
2020:                 */
2021:                public XblScopedChildNodes(XBLRecord rec) {
2022:                    super (rec);
2023:                }
2024:
2025:                /**
2026:                 * Update the NodeList.
2027:                 */
2028:                protected void update() {
2029:                    size = 0;
2030:                    Node shadowTree = getXblShadowTree(record.node);
2031:                    Node n = shadowTree == null ? record.node.getFirstChild()
2032:                            : shadowTree.getFirstChild();
2033:                    while (n != null) {
2034:                        collectXblScopedChildNodes(n);
2035:                        n = n.getNextSibling();
2036:                    }
2037:                }
2038:
2039:                /**
2040:                 * Find the XBL child nodes of this element.
2041:                 */
2042:                protected void collectXblScopedChildNodes(Node n) {
2043:                    boolean isChild = false;
2044:                    if (n.getNodeType() == Node.ELEMENT_NODE) {
2045:                        if (!n.getNamespaceURI().equals(XBL_NAMESPACE_URI)) {
2046:                            isChild = true;
2047:                        } else if (n instanceof  XBLOMContentElement) {
2048:                            ContentManager cm = getContentManager(n);
2049:                            if (cm != null) {
2050:                                NodeList selected = cm
2051:                                        .getSelectedContent((XBLOMContentElement) n);
2052:                                for (int i = 0; i < selected.getLength(); i++) {
2053:                                    collectXblScopedChildNodes(selected.item(i));
2054:                                }
2055:                            }
2056:                        }
2057:                    } else {
2058:                        isChild = true;
2059:                    }
2060:                    if (isChild) {
2061:                        nodes.add(n);
2062:                        size++;
2063:                    }
2064:                }
2065:            }
2066:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.