1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2005 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xerces.internal.jaxp.validation; 22 23 import java.util.ArrayList; 24 25 import javax.xml.transform.dom.DOMResult; 26 27 import com.sun.org.apache.xerces.internal.dom.AttrImpl; 28 import com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl; 29 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter; 30 import com.sun.org.apache.xerces.internal.dom.DocumentTypeImpl; 31 import com.sun.org.apache.xerces.internal.dom.ElementImpl; 32 import com.sun.org.apache.xerces.internal.dom.ElementNSImpl; 33 import com.sun.org.apache.xerces.internal.dom.EntityImpl; 34 import com.sun.org.apache.xerces.internal.dom.NotationImpl; 35 import com.sun.org.apache.xerces.internal.dom.PSVIAttrNSImpl; 36 import com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl; 37 import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; 38 import com.sun.org.apache.xerces.internal.impl.Constants; 39 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; 40 import com.sun.org.apache.xerces.internal.xni.Augmentations; 41 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 42 import com.sun.org.apache.xerces.internal.xni.QName; 43 import com.sun.org.apache.xerces.internal.xni.XMLAttributes; 44 import com.sun.org.apache.xerces.internal.xni.XMLLocator; 45 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; 46 import com.sun.org.apache.xerces.internal.xni.XMLString; 47 import com.sun.org.apache.xerces.internal.xni.XNIException; 48 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; 49 import com.sun.org.apache.xerces.internal.xs.AttributePSVI; 50 import com.sun.org.apache.xerces.internal.xs.ElementPSVI; 51 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; 52 53 import org.w3c.dom.CDATASection; 54 import org.w3c.dom.Comment; 55 import org.w3c.dom.Document; 56 import org.w3c.dom.DocumentType; 57 import org.w3c.dom.Element; 58 import org.w3c.dom.Entity; 59 import org.w3c.dom.NamedNodeMap; 60 import org.w3c.dom.Node; 61 import org.w3c.dom.Notation; 62 import org.w3c.dom.ProcessingInstruction; 63 import org.w3c.dom.Text; 64 65 66 /** 67 * <p>DOM result builder.</p> 68 * 69 * @author Michael Glavassevich, IBM 70 */ 71 final class DOMResultBuilder implements DOMDocumentHandler { 72 73 /** Table for quick check of child insertion. */ 74 private final static int[] kidOK; 75 76 static { 77 kidOK = new int[13]; 78 kidOK[Node.DOCUMENT_NODE] = 79 1 << Node.ELEMENT_NODE | 1 << Node.PROCESSING_INSTRUCTION_NODE | 80 1 << Node.COMMENT_NODE | 1 << Node.DOCUMENT_TYPE_NODE; 81 kidOK[Node.DOCUMENT_FRAGMENT_NODE] = 82 kidOK[Node.ENTITY_NODE] = 83 kidOK[Node.ENTITY_REFERENCE_NODE] = 84 kidOK[Node.ELEMENT_NODE] = 85 1 << Node.ELEMENT_NODE | 1 << Node.PROCESSING_INSTRUCTION_NODE | 86 1 << Node.COMMENT_NODE | 1 << Node.TEXT_NODE | 87 1 << Node.CDATA_SECTION_NODE | 1 << Node.ENTITY_REFERENCE_NODE ; 88 kidOK[Node.ATTRIBUTE_NODE] = 1 << Node.TEXT_NODE | 1 << Node.ENTITY_REFERENCE_NODE; 89 kidOK[Node.DOCUMENT_TYPE_NODE] = 0; 90 kidOK[Node.PROCESSING_INSTRUCTION_NODE] = 0; 91 kidOK[Node.COMMENT_NODE] = 0; 92 kidOK[Node.TEXT_NODE] = 0; 93 kidOK[Node.CDATA_SECTION_NODE] = 0; 94 kidOK[Node.NOTATION_NODE] = 0; 95 } // static 96 97 // 98 // Data 99 // 100 101 private Document fDocument; 102 private CoreDocumentImpl fDocumentImpl; 103 private boolean fStorePSVI; 104 105 private Node fTarget; 106 private Node fNextSibling; 107 108 private Node fCurrentNode; 109 private Node fFragmentRoot; 110 111 private final ArrayList fTargetChildren = new ArrayList(); 112 113 private boolean fIgnoreChars; 114 115 private final QName fAttributeQName = new QName(); 116 117 public DOMResultBuilder() {} 118 119 /* 120 * DOMDocumentHandler methods 121 */ 122 123 public void setDOMResult(DOMResult result) { 124 fCurrentNode = null; 125 fFragmentRoot = null; 126 fIgnoreChars = false; 127 fTargetChildren.clear(); 128 if (result != null) { 129 fTarget = result.getNode(); 130 fNextSibling = result.getNextSibling(); 131 fDocument = (fTarget.getNodeType() == Node.DOCUMENT_NODE) ? (Document) fTarget : fTarget.getOwnerDocument(); 132 fDocumentImpl = (fDocument instanceof CoreDocumentImpl) ? (CoreDocumentImpl) fDocument : null; 133 fStorePSVI = (fDocument instanceof PSVIDocumentImpl); 134 return; 135 } 136 fTarget = null; 137 fNextSibling = null; 138 fDocument = null; 139 fDocumentImpl = null; 140 fStorePSVI = false; 141 } 142 143 public void doctypeDecl(DocumentType node) throws XNIException { 144 /** Create new DocumentType node for the target. */ 145 if (fDocumentImpl != null) { 146 DocumentType docType = fDocumentImpl.createDocumentType(node.getName(), node.getPublicId(), node.getSystemId()); 147 final String internalSubset = node.getInternalSubset(); 148 /** Copy internal subset. */ 149 if (internalSubset != null) { 150 ((DocumentTypeImpl) docType).setInternalSubset(internalSubset); 151 } 152 /** Copy entities. */ 153 NamedNodeMap oldMap = node.getEntities(); 154 NamedNodeMap newMap = docType.getEntities(); 155 int length = oldMap.getLength(); 156 for (int i = 0; i < length; ++i) { 157 Entity oldEntity = (Entity) oldMap.item(i); 158 EntityImpl newEntity = (EntityImpl) fDocumentImpl.createEntity(oldEntity.getNodeName()); 159 newEntity.setPublicId(oldEntity.getPublicId()); 160 newEntity.setSystemId(oldEntity.getSystemId()); 161 newEntity.setNotationName(oldEntity.getNotationName()); 162 newMap.setNamedItem(newEntity); 163 } 164 /** Copy notations. */ 165 oldMap = node.getNotations(); 166 newMap = docType.getNotations(); 167 length = oldMap.getLength(); 168 for (int i = 0; i < length; ++i) { 169 Notation oldNotation = (Notation) oldMap.item(i); 170 NotationImpl newNotation = (NotationImpl) fDocumentImpl.createNotation(oldNotation.getNodeName()); 171 newNotation.setPublicId(oldNotation.getPublicId()); 172 newNotation.setSystemId(oldNotation.getSystemId()); 173 newMap.setNamedItem(newNotation); 174 } 175 append(docType); 176 } 177 } 178 179 public void characters(Text node) throws XNIException { 180 /** Create new Text node for the target. */ 181 append(fDocument.createTextNode(node.getNodeValue())); 182 } 183 184 public void cdata(CDATASection node) throws XNIException { 185 /** Create new CDATASection node for the target. */ 186 append(fDocument.createCDATASection(node.getNodeValue())); 187 } 188 189 public void comment(Comment node) throws XNIException { 190 /** Create new Comment node for the target. */ 191 append(fDocument.createComment(node.getNodeValue())); 192 } 193 194 public void processingInstruction(ProcessingInstruction node) 195 throws XNIException { 196 /** Create new ProcessingInstruction node for the target. */ 197 append(fDocument.createProcessingInstruction(node.getTarget(), node.getData())); 198 } 199 200 public void setIgnoringCharacters(boolean ignore) { 201 fIgnoreChars = ignore; 202 } 203 204 /* 205 * XMLDocumentHandler methods 206 */ 207 208 public void startDocument(XMLLocator locator, String encoding, 209 NamespaceContext namespaceContext, Augmentations augs) 210 throws XNIException {} 211 212 public void xmlDecl(String version, String encoding, String standalone, 213 Augmentations augs) throws XNIException {} 214 215 public void doctypeDecl(String rootElement, String publicId, 216 String systemId, Augmentations augs) throws XNIException {} 217 218 public void comment(XMLString text, Augmentations augs) throws XNIException {} 219 220 public void processingInstruction(String target, XMLString data, 221 Augmentations augs) throws XNIException {} 222 223 public void startElement(QName element, XMLAttributes attributes, 224 Augmentations augs) throws XNIException { 225 Element elem; 226 int attrCount = attributes.getLength(); 227 if (fDocumentImpl == null) { 228 elem = fDocument.createElementNS(element.uri, element.rawname); 229 for (int i = 0; i < attrCount; ++i) { 230 attributes.getName(i, fAttributeQName); 231 elem.setAttributeNS(fAttributeQName.uri, fAttributeQName.rawname, attributes.getValue(i)); 232 } 233 } 234 // If it's a Xerces DOM store type information for attributes, set idness, etc.. 235 else { 236 elem = fDocumentImpl.createElementNS(element.uri, element.rawname, element.localpart); 237 for (int i = 0; i < attrCount; ++i) { 238 attributes.getName(i, fAttributeQName); 239 AttrImpl attr = (AttrImpl) fDocumentImpl.createAttributeNS(fAttributeQName.uri, 240 fAttributeQName.rawname, fAttributeQName.localpart); 241 attr.setValue(attributes.getValue(i)); 242 243 // write type information to this attribute 244 AttributePSVI attrPSVI = (AttributePSVI) attributes.getAugmentations(i).getItem (Constants.ATTRIBUTE_PSVI); 245 if (attrPSVI != null) { 246 if (fStorePSVI) { 247 ((PSVIAttrNSImpl) attr).setPSVI(attrPSVI); 248 } 249 Object type = attrPSVI.getMemberTypeDefinition(); 250 if (type == null) { 251 type = attrPSVI.getTypeDefinition(); 252 if (type != null) { 253 attr.setType (type); 254 if (((XSSimpleType) type).isIDType()) { 255 ((ElementImpl) elem).setIdAttributeNode (attr, true); 256 } 257 } 258 } 259 else { 260 attr.setType (type); 261 if (((XSSimpleType) type).isIDType()) { 262 ((ElementImpl) elem).setIdAttributeNode (attr, true); 263 } 264 } 265 } 266 attr.setSpecified(attributes.isSpecified(i)); 267 elem.setAttributeNode(attr); 268 } 269 } 270 append(elem); 271 fCurrentNode = elem; 272 if (fFragmentRoot == null) { 273 fFragmentRoot = elem; 274 } 275 } 276 277 public void emptyElement(QName element, XMLAttributes attributes, 278 Augmentations augs) throws XNIException { 279 startElement(element, attributes, augs); 280 endElement(element, augs); 281 } 282 283 public void startGeneralEntity(String name, 284 XMLResourceIdentifier identifier, String encoding, 285 Augmentations augs) throws XNIException {} 286 287 public void textDecl(String version, String encoding, Augmentations augs) 288 throws XNIException {} 289 290 public void endGeneralEntity(String name, Augmentations augs) 291 throws XNIException {} 292 293 public void characters(XMLString text, Augmentations augs) 294 throws XNIException { 295 if (!fIgnoreChars) { 296 append(fDocument.createTextNode(text.toString())); 297 } 298 } 299 300 public void ignorableWhitespace(XMLString text, Augmentations augs) 301 throws XNIException { 302 characters(text, augs); 303 } 304 305 public void endElement(QName element, Augmentations augs) 306 throws XNIException { 307 // write type information to this element 308 if (augs != null && fDocumentImpl != null) { 309 ElementPSVI elementPSVI = (ElementPSVI)augs.getItem(Constants.ELEMENT_PSVI); 310 if (elementPSVI != null) { 311 if (fStorePSVI) { 312 ((PSVIElementNSImpl)fCurrentNode).setPSVI(elementPSVI); 313 } 314 XSTypeDefinition type = elementPSVI.getMemberTypeDefinition(); 315 if (type == null) { 316 type = elementPSVI.getTypeDefinition(); 317 } 318 ((ElementNSImpl)fCurrentNode).setType(type); 319 } 320 } 321 322 // adjust current node reference 323 if (fCurrentNode == fFragmentRoot) { 324 fCurrentNode = null; 325 fFragmentRoot = null; 326 return; 327 } 328 fCurrentNode = fCurrentNode.getParentNode(); 329 } 330 331 public void startCDATA(Augmentations augs) throws XNIException {} 332 333 public void endCDATA(Augmentations augs) throws XNIException {} 334 335 public void endDocument(Augmentations augs) throws XNIException { 336 final int length = fTargetChildren.size(); 337 if (fNextSibling == null) { 338 for (int i = 0; i < length; ++i) { 339 fTarget.appendChild((Node) fTargetChildren.get(i)); 340 } 341 } 342 else { 343 for (int i = 0; i < length; ++i) { 344 fTarget.insertBefore((Node) fTargetChildren.get(i), fNextSibling); 345 } 346 } 347 } 348 349 public void setDocumentSource(XMLDocumentSource source) {} 350 351 public XMLDocumentSource getDocumentSource() { 352 return null; 353 } 354 355 /* 356 * Other methods 357 */ 358 359 private void append(Node node) throws XNIException { 360 if (fCurrentNode != null) { 361 fCurrentNode.appendChild(node); 362 } 363 else { 364 /** Check if this node can be attached to the target. */ 365 if ((kidOK[fTarget.getNodeType()] & (1 << node.getNodeType())) == 0) { 366 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "HIERARCHY_REQUEST_ERR", null); 367 throw new XNIException(msg); 368 } 369 fTargetChildren.add(node); 370 } 371 } 372 373 } // DOMResultBuilder