|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | /* | 
|  |  * Licensed to the Apache Software Foundation (ASF) under one or more | 
|  |  * contributor license agreements.  See the NOTICE file distributed with | 
|  |  * this work for additional information regarding copyright ownership. | 
|  |  * The ASF licenses this file to You under the Apache License, Version 2.0 | 
|  |  * (the "License"); you may not use this file except in compliance with | 
|  |  * the License.  You may obtain a copy of the License at | 
|  |  * | 
|  |  *      http://www.apache.org/licenses/LICENSE-2.0 | 
|  |  * | 
|  |  * Unless required by applicable law or agreed to in writing, software | 
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  |  * See the License for the specific language governing permissions and | 
|  |  * limitations under the License. | 
|  |  */ | 
|  |  | 
|  | package com.sun.org.apache.xerces.internal.dom; | 
|  |  | 
|  | import com.sun.org.apache.xerces.internal.util.URI; | 
|  | import org.w3c.dom.DocumentType; | 
|  | import org.w3c.dom.EntityReference; | 
|  | import org.w3c.dom.NamedNodeMap; | 
|  | import org.w3c.dom.Node; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  */ | 
|  | public class EntityReferenceImpl | 
|  | extends ParentNode | 
|  | implements EntityReference { | 
|  |  | 
|  |     // | 
|  |     // Constants | 
|  |     // | 
|  |  | 
|  |      | 
|  |     static final long serialVersionUID = -7381452955687102062L; | 
|  |  | 
|  |     // | 
|  |     // Data | 
|  |     // | 
|  |  | 
|  |      | 
|  |     protected String name; | 
|  |      | 
|  |     protected String baseURI; | 
|  |  | 
|  |  | 
|  |     /** Entity changes. */ | 
|  |     //protected int entityChanges = -1; | 
|  |  | 
|  |     /** Enable synchronize. */ | 
|  |     //protected boolean fEnableSynchronize = false; | 
|  |  | 
|  |     // | 
|  |     // Constructors | 
|  |     // | 
|  |  | 
|  |      | 
|  |     public EntityReferenceImpl(CoreDocumentImpl ownerDoc, String name) { | 
|  |         super(ownerDoc); | 
|  |         this.name = name; | 
|  |         isReadOnly(true); | 
|  |         needsSyncChildren(true); | 
|  |     } | 
|  |  | 
|  |     // | 
|  |     // Node methods | 
|  |     // | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public short getNodeType() { | 
|  |         return Node.ENTITY_REFERENCE_NODE; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |      */ | 
|  |     public String getNodeName() { | 
|  |         if (needsSyncData()) { | 
|  |             synchronizeData(); | 
|  |         } | 
|  |         return name; | 
|  |     } | 
|  |  | 
|  |      | 
|  |     public Node cloneNode(boolean deep) { | 
|  |         EntityReferenceImpl er = (EntityReferenceImpl)super.cloneNode(deep); | 
|  |         er.setReadOnly(true, deep); | 
|  |         return er; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public String getBaseURI() { | 
|  |         if (needsSyncData()) { | 
|  |             synchronizeData(); | 
|  |         } | 
|  |         if (baseURI == null) { | 
|  |             DocumentType doctype; | 
|  |             NamedNodeMap entities; | 
|  |             EntityImpl entDef; | 
|  |             if (null != (doctype = getOwnerDocument().getDoctype()) && | 
|  |                 null != (entities = doctype.getEntities())) { | 
|  |  | 
|  |                 entDef = (EntityImpl)entities.getNamedItem(getNodeName()); | 
|  |                 if (entDef !=null) { | 
|  |                     return entDef.getBaseURI(); | 
|  |                 } | 
|  |             } | 
|  |         } else if (baseURI != null && baseURI.length() != 0 ) { | 
|  |             try { | 
|  |                 return new URI(baseURI).toString(); | 
|  |             } | 
|  |             catch (com.sun.org.apache.xerces.internal.util.URI.MalformedURIException e){ | 
|  |                  | 
|  |                 return null; | 
|  |             } | 
|  |         } | 
|  |         return baseURI; | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |     public void setBaseURI(String uri){ | 
|  |         if (needsSyncData()) { | 
|  |             synchronizeData(); | 
|  |         } | 
|  |         baseURI = uri; | 
|  |     } | 
|  |  | 
|  |          | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |          */ | 
|  |     protected String getEntityRefValue (){ | 
|  |         if (needsSyncChildren()){ | 
|  |             synchronizeChildren(); | 
|  |         } | 
|  |  | 
|  |         String value = ""; | 
|  |         if (firstChild != null){ | 
|  |           if (firstChild.getNodeType() == Node.ENTITY_REFERENCE_NODE){ | 
|  |               value = ((EntityReferenceImpl)firstChild).getEntityRefValue(); | 
|  |           } | 
|  |           else if (firstChild.getNodeType() == Node.TEXT_NODE){ | 
|  |             value = firstChild.getNodeValue(); | 
|  |           } | 
|  |           else { | 
|  |               | 
|  |             return null; | 
|  |           } | 
|  |  | 
|  |           if (firstChild.nextSibling == null){ | 
|  |             return value; | 
|  |           } | 
|  |           else { | 
|  |             StringBuffer buff = new StringBuffer(value); | 
|  |             ChildNode next = firstChild.nextSibling; | 
|  |             while (next != null){ | 
|  |  | 
|  |                 if (next.getNodeType() == Node.ENTITY_REFERENCE_NODE){ | 
|  |                    value = ((EntityReferenceImpl)next).getEntityRefValue(); | 
|  |                 } | 
|  |                 else if (next.getNodeType() == Node.TEXT_NODE){ | 
|  |                   value = next.getNodeValue(); | 
|  |                 } | 
|  |                 else { | 
|  |                      | 
|  |                     return null; | 
|  |                 } | 
|  |                 buff.append(value); | 
|  |                 next = next.nextSibling; | 
|  |  | 
|  |             } | 
|  |             return buff.toString(); | 
|  |           } | 
|  |         } | 
|  |         return ""; | 
|  |     } | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     protected void synchronizeChildren() { | 
|  |          | 
|  |         needsSyncChildren(false); | 
|  |  | 
|  |         DocumentType doctype; | 
|  |         NamedNodeMap entities; | 
|  |         EntityImpl entDef; | 
|  |         if (null != (doctype = getOwnerDocument().getDoctype()) && | 
|  |             null != (entities = doctype.getEntities())) { | 
|  |  | 
|  |             entDef = (EntityImpl)entities.getNamedItem(getNodeName()); | 
|  |  | 
|  |              | 
|  |             if (entDef == null) | 
|  |                 return; | 
|  |  | 
|  |              | 
|  |             isReadOnly(false); | 
|  |             for (Node defkid = entDef.getFirstChild(); | 
|  |                 defkid != null; | 
|  |                 defkid = defkid.getNextSibling()) { | 
|  |                 Node newkid = defkid.cloneNode(true); | 
|  |                 insertBefore(newkid, null); | 
|  |             } | 
|  |             setReadOnly(true, true); | 
|  |         } | 
|  |     } | 
|  |  | 
|  |  | 
|  |      | 
|  |  | 
|  |  | 
|  |  | 
|  |      */ | 
|  |     public void setReadOnly(boolean readOnly, boolean deep) { | 
|  |  | 
|  |         if (needsSyncData()) { | 
|  |             synchronizeData(); | 
|  |         } | 
|  |         if (deep) { | 
|  |  | 
|  |             if (needsSyncChildren()) { | 
|  |                 synchronizeChildren(); | 
|  |             } | 
|  |              | 
|  |             for (ChildNode mykid = firstChild; | 
|  |                  mykid != null; | 
|  |                  mykid = mykid.nextSibling) { | 
|  |  | 
|  |                 mykid.setReadOnly(readOnly,true); | 
|  |  | 
|  |             } | 
|  |         } | 
|  |         isReadOnly(readOnly); | 
|  |     } // setReadOnly(boolean,boolean) | 
|  |  | 
|  |  | 
|  |     /** | 
|  |      * Enable the synchronize method which may do cloning. This method is enabled | 
|  |      * when the parser is done with an EntityReference. | 
|  |     /*** | 
|  |     // revisit: enable editing of Entity | 
|  |     public void enableSynchronize(boolean enableSynchronize) { | 
|  |         fEnableSynchronize= enableSynchronize; | 
|  |     } | 
|  |     /***/ | 
|  |  | 
|  |     /** | 
|  |      * EntityReference's children are a reflection of those defined in the | 
|  |      * named Entity. This method updates them if the Entity is changed. | 
|  |      * <P> | 
|  |      * It is unclear what the least-cost resynch mechanism is. | 
|  |      * If we expect the kids to be shallow, and/or expect changes | 
|  |      * to the Entity contents to be rare, wiping them all out | 
|  |      * and recloning is simplest. | 
|  |      * <P> | 
|  |      * If we expect them to be deep, | 
|  |      * it might be better to first decide which kids (if any) | 
|  |      * persist, and keep the ones (if any) that are unchanged | 
|  |      * rather than doing all the work of cloning them again. | 
|  |      * But that latter gets into having to convolve the two child lists, | 
|  |      * insert new information in the right order (and possibly reorder | 
|  |      * the existing kids), and a few other complexities that I really | 
|  |      * don't want to deal with in this implementation. | 
|  |      * <P> | 
|  |      * Note that if we decide that we need to update the EntityReference's | 
|  |      * contents, we have to turn off the readOnly flag temporarily to do so. | 
|  |      * When we get around to adding multitasking support, this whole method | 
|  |      * should probably be an atomic operation. | 
|  |      * | 
|  |      * @see DocumentTypeImpl | 
|  |      * @see EntityImpl | 
|  |      */ | 
|  |     // The Xerces parser invokes callbacks for startEntityReference | 
|  |     // the parsed value of the entity EACH TIME, so it is actually | 
|  |     // easier to create the nodes through the callbacks rather than | 
|  |     // clone the Entity. | 
|  |     /*** | 
|  |     // revisit: enable editing of Entity | 
|  |     private void synchronize() { | 
|  |         if (!fEnableSynchronize) { | 
|  |             return; | 
|  |         } | 
|  |         DocumentType doctype; | 
|  |         NamedNodeMap entities; | 
|  |         EntityImpl entDef; | 
|  |         if (null != (doctype = getOwnerDocument().getDoctype()) && | 
|  |             null != (entities = doctype.getEntities())) { | 
|  |  | 
|  |             entDef = (EntityImpl)entities.getNamedItem(getNodeName()); | 
|  |  | 
|  |             // No Entity by this name. If we had a change count, reset it. | 
|  |             if(null==entDef) | 
|  |                 entityChanges=-1; | 
|  |  | 
|  |             // If no kids availalble, wipe any pre-existing children. | 
|  |             // (See discussion above.) | 
|  |             // Note that we have to use the superclass to avoid recursion | 
|  |             // through Synchronize. | 
|  |             readOnly=false; | 
|  |             if(null==entDef || !entDef.hasChildNodes()) | 
|  |                 for(Node kid=super.getFirstChild(); | 
|  |                     kid!=null; | 
|  |                     kid=super.getFirstChild()) | 
|  |                     removeChild(kid); | 
|  |  | 
|  |             // If entity's definition changed, clone its kids | 
|  |             // (See discussion above.) | 
|  |             if(null!=entDef && entDef.changes!=entityChanges) { | 
|  |                 for(Node defkid=entDef.getFirstChild(); | 
|  |                     defkid!=null; | 
|  |                     defkid=defkid.getNextSibling()) { | 
|  |  | 
|  |                     NodeImpl newkid=(NodeImpl) defkid.cloneNode(true); | 
|  |                     newkid.setReadOnly(true,true); | 
|  |                     insertBefore(newkid,null); | 
|  |                 } | 
|  |                 entityChanges=entDef.changes; | 
|  |             } | 
|  |             readOnly=true; | 
|  |         } | 
|  |     } | 
|  |      /***/ | 
|  |  | 
|  |  | 
|  | } // class EntityReferenceImpl |