KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > xpath > datamodel > xerces > dom > EntityReferenceImpl


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package org.xquark.xpath.datamodel.xerces.dom;
59
60 import org.w3c.dom.*;
61
62 /**
63  * EntityReference models the XML &entityname; syntax, when used for
64  * entities defined by the DOM. Entities hardcoded into XML, such as
65  * character entities, should instead have been translated into text
66  * by the code which generated the DOM tree.
67  * <P>
68  * An XML processor has the alternative of fully expanding Entities
69  * into the normal document tree. If it does so, no EntityReference nodes
70  * will appear.
71  * <P>
72  * Similarly, non-validating XML processors are not required to read
73  * or process entity declarations made in the external subset or
74  * declared in external parameter entities. Hence, some applications
75  * may not make the replacement value available for Parsed Entities
76  * of these types.
77  * <P>
78  * EntityReference behaves as a read-only node, and the children of
79  * the EntityReference (which reflect those of the Entity, and should
80  * also be read-only) give its replacement value, if any. They are
81  * supposed to automagically stay in synch if the DocumentType is
82  * updated with new values for the Entity.
83  * <P>
84  * The defined behavior makes efficient storage difficult for the DOM
85  * implementor. We can't just look aside to the Entity's definition
86  * in the DocumentType since those nodes have the wrong parent (unless
87  * we can come up with a clever "imaginary parent" mechanism). We
88  * must at least appear to clone those children... which raises the
89  * issue of keeping the reference synchronized with its parent.
90  * This leads me back to the "cached image of centrally defined data"
91  * solution, much as I dislike it.
92  * <P>
93  * For now I have decided, since REC-DOM-Level-1-19980818 doesn't
94  * cover this in much detail, that synchronization doesn't have to be
95  * considered while the user is deep in the tree. That is, if you're
96  * looking within one of the EntityReferennce's children and the Entity
97  * changes, you won't be informed; instead, you will continue to access
98  * the same object -- which may or may not still be part of the tree.
99  * This is the same behavior that obtains elsewhere in the DOM if the
100  * subtree you're looking at is deleted from its parent, so it's
101  * acceptable here. (If it really bothers folks, we could set things
102  * up so deleted subtrees are walked and marked invalid, but that's
103  * not part of the DOM's defined behavior.)
104  * <P>
105  * As a result, only the EntityReference itself has to be aware of
106  * changes in the Entity. And it can take advantage of the same
107  * structure-change-monitoring code I implemented to support
108  * DeepNodeList.
109  *
110  * @author Arnaud Le Hors, IBM
111  * @author Joe Kesselman, IBM
112  * @author Andy Clark, IBM
113  * @author Ralf Pfeiffer, IBM
114  * @version
115  * @since PR-DOM-Level-1-19980818.
116  */

117 public class EntityReferenceImpl
118     extends ParentNode
119     implements EntityReference {
120
121     //
122
// Constants
123
//
124

125     /** Serialization version. */
126     static final long serialVersionUID = -7381452955687102062L;
127     
128     //
129
// Data
130
//
131

132     /** Name of Entity referenced */
133     protected String JavaDoc name;
134
135     /** Entity changes. */
136     //protected int entityChanges = -1;
137

138     /** Enable synchronize. */
139     //protected boolean fEnableSynchronize = false;
140

141     //
142
// Constructors
143
//
144

145     /** Factory constructor. */
146     public EntityReferenceImpl(DocumentImpl ownerDoc, String JavaDoc name) {
147         super(ownerDoc);
148         this.name = name;
149         isReadOnly(true);
150     }
151     
152     //
153
// Node methods
154
//
155

156     /**
157      * A short integer indicating what type of node this is. The named
158      * constants for this value are defined in the org.w3c.dom.Node interface.
159      */

160     public short getNodeType() {
161         return Node.ENTITY_REFERENCE_NODE;
162     }
163
164     /**
165      * Returns the name of the entity referenced
166      */

167     public String JavaDoc getNodeName() {
168         if (needsSyncData()) {
169             synchronizeData();
170         }
171         return name;
172     }
173
174     // REVISIT: Return original entity reference code. -Ac
175

176     /**
177      * Perform synchronize() before accessing children.
178      *
179      * @return org.w3c.dom.NodeList
180      */

181     public NodeList getChildNodes() {
182         synchronize();
183         return super.getChildNodes();
184     }
185
186     /**
187      * Perform synchronize() before accessing children.
188      *
189      * @return org.w3c.dom.NodeList
190      */

191     public Node getFirstChild() {
192         synchronize();
193         return super.getFirstChild();
194     }
195
196     /**
197      * Perform synchronize() before accessing children.
198      *
199      * @return org.w3c.dom.NodeList
200      */

201     public Node getLastChild() {
202         synchronize();
203         return super.getLastChild();
204     }
205
206     /**
207      * Query the number of children in the entity definition.
208      * (A bit more work than asking locally, but may be able to avoid
209      * or defer building the clone subtree.)
210      *
211      * @return org.w3c.dom.NodeList
212      */

213     public int getLength() {
214         synchronize();
215         return super.getLength();
216     }
217
218     /**
219      * Returns whether this node has any children.
220      * @return boolean
221      */

222     public boolean hasChildNodes() {
223         synchronize();
224         return super.hasChildNodes();
225     }
226
227     /** Returns the node at the given index. */
228     public Node item(int index) {
229         synchronize();
230         return super.item(index);
231     }
232
233
234     /**
235      * EntityReference's children are a reflection of those defined in the
236      * named Entity. This method creates them if they haven't been created yet.
237      * This doesn't really support editing the Entity though.
238      */

239     protected void synchronize() {
240         if (firstChild != null) {
241             return;
242         }
243         DocumentType doctype;
244         NamedNodeMap entities;
245         EntityImpl entDef;
246         if (null != (doctype = getOwnerDocument().getDoctype()) &&
247             null != (entities = doctype.getEntities())) {
248             
249             entDef = (EntityImpl)entities.getNamedItem(getNodeName());
250
251             // No Entity by this name, stop here.
252
if (entDef == null)
253                 return;
254
255             // If entity's definition exists, clone its kids
256
isReadOnly(false);
257             for (Node defkid = entDef.getFirstChild();
258                  defkid != null;
259                  defkid = defkid.getNextSibling()) {
260                 Node newkid = defkid.cloneNode(true);
261                 insertBefore(newkid,null);
262             }
263             setReadOnly(true, true);
264         }
265     }
266
267
268     /**
269      * Enable the synchronize method which may do cloning. This method is enabled
270      * when the parser is done with an EntityReference.
271     /***
272     // revisit: enable editing of Entity
273     public void enableSynchronize(boolean enableSynchronize) {
274         fEnableSynchronize= enableSynchronize;
275     }
276     /***/

277
278     /**
279      * EntityReference's children are a reflection of those defined in the
280      * named Entity. This method updates them if the Entity is changed.
281      * <P>
282      * It is unclear what the least-cost resynch mechanism is.
283      * If we expect the kids to be shallow, and/or expect changes
284      * to the Entity contents to be rare, wiping them all out
285      * and recloning is simplest.
286      * <P>
287      * If we expect them to be deep,
288      * it might be better to first decide which kids (if any)
289      * persist, and keep the ones (if any) that are unchanged
290      * rather than doing all the work of cloning them again.
291      * But that latter gets into having to convolve the two child lists,
292      * insert new information in the right order (and possibly reorder
293      * the existing kids), and a few other complexities that I really
294      * don't want to deal with in this implementation.
295      * <P>
296      * Note that if we decide that we need to update the EntityReference's
297      * contents, we have to turn off the readOnly flag temporarily to do so.
298      * When we get around to adding multitasking support, this whole method
299      * should probably be an atomic operation.
300      *
301      * @see DocumentTypeImpl
302      * @see EntityImpl
303      */

304      // The Xerces parser invokes callbacks for startEnityReference
305
// the parsed value of the entity EACH TIME, so it is actually
306
// easier to create the nodes through the callbacks rather than
307
// clone the Entity.
308
/***
309     // revisit: enable editing of Entity
310     private void synchronize() {
311         if (!fEnableSynchronize) {
312             return;
313         }
314         DocumentType doctype;
315         NamedNodeMap entities;
316         EntityImpl entDef;
317         if (null != (doctype = getOwnerDocument().getDoctype()) &&
318             null != (entities = doctype.getEntities())) {
319             
320             entDef = (EntityImpl)entities.getNamedItem(getNodeName());
321
322             // No Entity by this name. If we had a change count, reset it.
323             if(null==entDef)
324                 entityChanges=-1;
325
326             // If no kids availalble, wipe any pre-existing children.
327             // (See discussion above.)
328             // Note that we have to use the superclass to avoid recursion
329             // through Synchronize.
330             readOnly=false;
331             if(null==entDef || !entDef.hasChildNodes())
332                 for(Node kid=super.getFirstChild();
333                     kid!=null;
334                     kid=super.getFirstChild())
335                     removeChild(kid);
336
337             // If entity's definition changed, clone its kids
338             // (See discussion above.)
339             if(null!=entDef && entDef.changes!=entityChanges) {
340                 for(Node defkid=entDef.getFirstChild();
341                     defkid!=null;
342                     defkid=defkid.getNextSibling()) {
343                     
344                     NodeImpl newkid=(NodeImpl) defkid.cloneNode(true);
345                     newkid.setReadOnly(true,true);
346                     insertBefore(newkid,null);
347                 }
348                 entityChanges=entDef.changes;
349             }
350             readOnly=true;
351         }
352     }
353      /***/

354     
355 } // class EntityReferenceImpl
356
Popular Tags