KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > dom > EntityReferenceImpl


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

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

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

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

144     /** Enable synchronize. */
145     //protected boolean fEnableSynchronize = false;
146

147     //
148
// Constructors
149
//
150

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

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

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

174     public String JavaDoc getNodeName() {
175         if (needsSyncData()) {
176             synchronizeData();
177         }
178         return name;
179     }
180
181     /** Clone node. */
182     public Node JavaDoc cloneNode(boolean deep) {
183         EntityReferenceImpl er = (EntityReferenceImpl)super.cloneNode(deep);
184         er.setReadOnly(true, deep);
185         return er;
186     }
187
188     /**
189      * DOM Level 3 WD - Experimental.
190      * Retrieve baseURI
191      */

192     public String JavaDoc getBaseURI() {
193         if (needsSyncData()) {
194             synchronizeData();
195         }
196         if (baseURI == null) {
197             DocumentType JavaDoc doctype;
198             NamedNodeMap JavaDoc entities;
199             EntityImpl entDef;
200             if (null != (doctype = getOwnerDocument().getDoctype()) &&
201                 null != (entities = doctype.getEntities())) {
202
203                 entDef = (EntityImpl)entities.getNamedItem(getNodeName());
204                 if (entDef !=null) {
205                     return entDef.getBaseURI();
206                 }
207             }
208         }
209         return baseURI;
210     }
211
212
213     /** NON-DOM: set base uri*/
214     public void setBaseURI(String JavaDoc uri){
215         if (needsSyncData()) {
216             synchronizeData();
217         }
218         baseURI = uri;
219     }
220     
221     /**
222      * NON-DOM: compute string representation of the entity reference.
223      * This method is used to retrieve a string value for an attribute node that has child nodes.
224      * @return String representing a value of this entity ref. or
225      * null if any node other than EntityReference, Text is encountered
226      * during computation
227      */

228     protected String JavaDoc getEntityRefValue (){
229         if (needsSyncChildren()){
230             synchronizeChildren();
231         }
232        
233         String JavaDoc value = "";
234         if (firstChild != null){
235           if (firstChild.getNodeType() == Node.ENTITY_REFERENCE_NODE){
236               value = ((EntityReferenceImpl)firstChild).getEntityRefValue();
237           }
238           else if (firstChild.getNodeType() == Node.TEXT_NODE){
239             value = firstChild.getNodeValue();
240           }
241           else {
242              // invalid to have other types of nodes in attr value
243
return null;
244           }
245           
246           if (firstChild.nextSibling == null){
247             return value;
248           }
249           else {
250             StringBuffer JavaDoc buff = new StringBuffer JavaDoc(value);
251             ChildNode next = firstChild.nextSibling;
252             while (next != null){
253             
254                 if (next.getNodeType() == Node.ENTITY_REFERENCE_NODE){
255                    value = ((EntityReferenceImpl)next).getEntityRefValue();
256                 }
257                 else if (next.getNodeType() == Node.TEXT_NODE){
258                   value = next.getNodeValue();
259                 }
260                 else {
261                     // invalid to have other types of nodes in attr value
262
return null;
263                 }
264                 buff.append(value);
265                 next = next.nextSibling;
266
267             }
268             return buff.toString();
269           }
270         }
271         return "";
272     }
273
274     /**
275      * EntityReference's children are a reflection of those defined in the
276      * named Entity. This method creates them if they haven't been created yet.
277      * This doesn't support editing the Entity though, since this only called
278      * once for all.
279      */

280     protected void synchronizeChildren() {
281         // no need to synchronize again
282
needsSyncChildren(false);
283
284         DocumentType JavaDoc doctype;
285         NamedNodeMap JavaDoc entities;
286         EntityImpl entDef;
287         if (null != (doctype = getOwnerDocument().getDoctype()) &&
288             null != (entities = doctype.getEntities())) {
289
290             entDef = (EntityImpl)entities.getNamedItem(getNodeName());
291
292             // No Entity by this name, stop here.
293
if (entDef == null)
294                 return;
295
296             // If entity's definition exists, clone its kids
297
isReadOnly(false);
298             for (Node JavaDoc defkid = entDef.getFirstChild();
299                 defkid != null;
300                 defkid = defkid.getNextSibling()) {
301                 Node JavaDoc newkid = defkid.cloneNode(true);
302                 insertBefore(newkid, null);
303             }
304             setReadOnly(true, true);
305         }
306     }
307
308
309     /**
310      * NON-DOM: sets the node and its children value.
311      * <P>
312      * Note: make sure that entity reference and its kids could be set readonly.
313      */

314     public void setReadOnly(boolean readOnly, boolean deep) {
315
316         if (needsSyncData()) {
317             synchronizeData();
318         }
319         if (deep) {
320
321             if (needsSyncChildren()) {
322                 synchronizeChildren();
323             }
324             // Recursively set kids
325
for (ChildNode mykid = firstChild;
326                  mykid != null;
327                  mykid = mykid.nextSibling) {
328                      
329                 mykid.setReadOnly(readOnly,true);
330                 
331             }
332         }
333         isReadOnly(readOnly);
334     } // setReadOnly(boolean,boolean)
335

336
337     /**
338      * Enable the synchronize method which may do cloning. This method is enabled
339      * when the parser is done with an EntityReference.
340     /***
341     // revisit: enable editing of Entity
342     public void enableSynchronize(boolean enableSynchronize) {
343         fEnableSynchronize= enableSynchronize;
344     }
345     /***/

346
347     /**
348      * EntityReference's children are a reflection of those defined in the
349      * named Entity. This method updates them if the Entity is changed.
350      * <P>
351      * It is unclear what the least-cost resynch mechanism is.
352      * If we expect the kids to be shallow, and/or expect changes
353      * to the Entity contents to be rare, wiping them all out
354      * and recloning is simplest.
355      * <P>
356      * If we expect them to be deep,
357      * it might be better to first decide which kids (if any)
358      * persist, and keep the ones (if any) that are unchanged
359      * rather than doing all the work of cloning them again.
360      * But that latter gets into having to convolve the two child lists,
361      * insert new information in the right order (and possibly reorder
362      * the existing kids), and a few other complexities that I really
363      * don't want to deal with in this implementation.
364      * <P>
365      * Note that if we decide that we need to update the EntityReference's
366      * contents, we have to turn off the readOnly flag temporarily to do so.
367      * When we get around to adding multitasking support, this whole method
368      * should probably be an atomic operation.
369      *
370      * @see DocumentTypeImpl
371      * @see EntityImpl
372      */

373     // The Xerces parser invokes callbacks for startEnityReference
374
// the parsed value of the entity EACH TIME, so it is actually
375
// easier to create the nodes through the callbacks rather than
376
// clone the Entity.
377
/***
378     // revisit: enable editing of Entity
379     private void synchronize() {
380         if (!fEnableSynchronize) {
381             return;
382         }
383         DocumentType doctype;
384         NamedNodeMap entities;
385         EntityImpl entDef;
386         if (null != (doctype = getOwnerDocument().getDoctype()) &&
387             null != (entities = doctype.getEntities())) {
388             
389             entDef = (EntityImpl)entities.getNamedItem(getNodeName());
390
391             // No Entity by this name. If we had a change count, reset it.
392             if(null==entDef)
393                 entityChanges=-1;
394
395             // If no kids availalble, wipe any pre-existing children.
396             // (See discussion above.)
397             // Note that we have to use the superclass to avoid recursion
398             // through Synchronize.
399             readOnly=false;
400             if(null==entDef || !entDef.hasChildNodes())
401                 for(Node kid=super.getFirstChild();
402                     kid!=null;
403                     kid=super.getFirstChild())
404                     removeChild(kid);
405
406             // If entity's definition changed, clone its kids
407             // (See discussion above.)
408             if(null!=entDef && entDef.changes!=entityChanges) {
409                 for(Node defkid=entDef.getFirstChild();
410                     defkid!=null;
411                     defkid=defkid.getNextSibling()) {
412                     
413                     NodeImpl newkid=(NodeImpl) defkid.cloneNode(true);
414                     newkid.setReadOnly(true,true);
415                     insertBefore(newkid,null);
416                 }
417                 entityChanges=entDef.changes;
418             }
419             readOnly=true;
420         }
421     }
422      /***/

423
424
425 } // class EntityReferenceImpl
426
Popular Tags