KickJava   Java API By Example, From Geeks To Geeks.

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

121 public class EntityReferenceImpl
122     extends ParentNode
123     implements EntityReference JavaDoc {
124
125     //
126
// Constants
127
//
128

129     /** Serialization version. */
130     static final long serialVersionUID = -7381452955687102062L;
131     
132     //
133
// Data
134
//
135

136     /** Name of Entity referenced */
137     protected String JavaDoc name;
138
139     /** Entity changes. */
140     //protected int entityChanges = -1;
141

142     /** Enable synchronize. */
143     //protected boolean fEnableSynchronize = false;
144

145     //
146
// Constructors
147
//
148

149     /** Factory constructor. */
150     public EntityReferenceImpl(CoreDocumentImpl ownerDoc, String JavaDoc name) {
151         super(ownerDoc);
152         this.name = name;
153         //FIXME: Enhydra:
154
// isReadOnly(true);
155
}
156     
157     //
158
// Node methods
159
//
160

161     /**
162      * A short integer indicating what type of node this is. The named
163      * constants for this value are defined in the org.w3c.dom.Node interface.
164      */

165     public short getNodeType() {
166         return Node.ENTITY_REFERENCE_NODE;
167     }
168
169     /**
170      * Returns the name of the entity referenced
171      */

172     public String JavaDoc getNodeName() {
173         if (needsSyncData()) {
174             synchronizeData();
175         }
176         return name;
177     }
178
179     // REVISIT: Return original entity reference code. -Ac
180

181     /**
182      * Perform synchronize() before accessing children.
183      *
184      * @return org.w3c.dom.NodeList
185      */

186     public NodeList JavaDoc getChildNodes() {
187         synchronize();
188         return super.getChildNodes();
189     }
190
191     /**
192      * Perform synchronize() before accessing children.
193      *
194      * @return org.w3c.dom.NodeList
195      */

196     public Node JavaDoc getFirstChild() {
197         synchronize();
198         return super.getFirstChild();
199     }
200
201     /**
202      * Perform synchronize() before accessing children.
203      *
204      * @return org.w3c.dom.NodeList
205      */

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

218     public int getLength() {
219         synchronize();
220         return super.getLength();
221     }
222
223     /**
224      * Returns whether this node has any children.
225      * @return boolean
226      */

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

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

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

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

359     
360 } // class EntityReferenceImpl
361
Popular Tags