|
|
|
|
|
|
|
*/ |
|
/* |
|
* 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 |