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