Source for gnu.xml.libxmlj.dom.GnomeDocument

   1: /* GnomeDocument.java -
   2:    Copyright (C) 2004 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.xml.libxmlj.dom;
  39: 
  40: import gnu.java.lang.CPStringBuilder;
  41: import gnu.xml.dom.DomNodeIterator;
  42: 
  43: import java.util.Iterator;
  44: 
  45: import org.w3c.dom.Attr;
  46: import org.w3c.dom.CDATASection;
  47: import org.w3c.dom.Comment;
  48: import org.w3c.dom.Document;
  49: import org.w3c.dom.DocumentFragment;
  50: import org.w3c.dom.DocumentType;
  51: import org.w3c.dom.DOMConfiguration;
  52: import org.w3c.dom.DOMErrorHandler;
  53: import org.w3c.dom.DOMException;
  54: import org.w3c.dom.DOMImplementation;
  55: import org.w3c.dom.DOMStringList;
  56: import org.w3c.dom.Element;
  57: import org.w3c.dom.EntityReference;
  58: import org.w3c.dom.Node;
  59: import org.w3c.dom.NodeList;
  60: import org.w3c.dom.ProcessingInstruction;
  61: import org.w3c.dom.Text;
  62: import org.w3c.dom.UserDataHandler;
  63: import org.w3c.dom.traversal.DocumentTraversal;
  64: import org.w3c.dom.traversal.NodeFilter;
  65: import org.w3c.dom.traversal.NodeIterator;
  66: import org.w3c.dom.traversal.TreeWalker;
  67: import org.w3c.dom.xpath.XPathEvaluator;
  68: import org.w3c.dom.xpath.XPathException;
  69: import org.w3c.dom.xpath.XPathExpression;
  70: import org.w3c.dom.xpath.XPathNSResolver;
  71: 
  72: /**
  73:  * A DOM document node implemented in libxml2.
  74:  *
  75:  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
  76:  */
  77: public class GnomeDocument
  78:   extends GnomeNode
  79:   implements Document, DOMConfiguration, XPathEvaluator, DocumentTraversal
  80: {
  81: 
  82:   DOMImplementation dom;
  83: 
  84:   /**
  85:    * Not currently used.
  86:    */
  87:   boolean strictErrorChecking;
  88: 
  89:   /* DOMConfiguration */
  90:   boolean canonicalForm = false;
  91:   boolean cdataSections = true;
  92:   boolean checkCharacterNormalization = false;
  93:   boolean comments = true;
  94:   boolean datatypeNormalization = false;
  95:   boolean elementContentWhitespace = true;
  96:   boolean entities = true;
  97:   DOMErrorHandler errorHandler;
  98:   boolean namespaces = true;
  99:   boolean namespaceDeclarations = true;
 100:   boolean normalizeCharacters = false;
 101:   boolean splitCdataSections = true;
 102:   boolean validate = false;
 103:   boolean validateIfSchema = false;
 104:   boolean wellFormed = true;
 105: 
 106:   GnomeDocument(Object id)
 107:   {
 108:     super(id);
 109:     strictErrorChecking = true;
 110:   }
 111: 
 112:   protected void finalize()
 113:   {
 114:     free(id);
 115:   }
 116: 
 117:   private native void free(Object id);
 118: 
 119:   public native DocumentType getDoctype();
 120: 
 121:   public DOMImplementation getImplementation()
 122:   {
 123:     return dom;
 124:   }
 125: 
 126:   public native Element getDocumentElement();
 127: 
 128:   public Element createElement(String tagName)
 129:     throws DOMException
 130:   {
 131:     return createElementNS(null, tagName);
 132:   }
 133: 
 134:   public native DocumentType createDocumentType(String name, String publicId,
 135:                                                 String systemId);
 136: 
 137:   public native DocumentFragment createDocumentFragment();
 138: 
 139:   public native Text createTextNode(String data);
 140: 
 141:   public native Comment createComment(String data);
 142: 
 143:   public native CDATASection createCDATASection(String data)
 144:     throws DOMException;
 145: 
 146:   public native ProcessingInstruction createProcessingInstruction(String target,
 147:                                                                   String data)
 148:     throws DOMException;
 149: 
 150:   public Attr createAttribute(String name)
 151:     throws DOMException
 152:   {
 153:     return createAttributeNS(null, name);
 154:   }
 155: 
 156:   public native EntityReference createEntityReference(String name)
 157:     throws DOMException;
 158: 
 159:   public native NodeList getElementsByTagName(String tagName);
 160: 
 161:   public Node importNode(Node importedNode, boolean deep)
 162:     throws DOMException
 163:   {
 164:     Node ret = xmljImportNode(importedNode, deep);
 165:     if (importedNode instanceof GnomeNode)
 166:       {
 167:         ((GnomeNode) importedNode)
 168:           .notifyUserDataHandlers(UserDataHandler.NODE_IMPORTED,
 169:                                   importedNode, ret);
 170:       }
 171:     return ret;
 172:   }
 173: 
 174:   private native Node xmljImportNode(Node importedNode, boolean deep)
 175:     throws DOMException;
 176: 
 177:   public native Element createElementNS(String namespaceURI, String
 178:                                         qualifiedName)
 179:     throws DOMException;
 180: 
 181:   public native Attr createAttributeNS(String namespaceURI, String
 182:                                        qualifiedName)
 183:     throws DOMException;
 184: 
 185:   public native NodeList getElementsByTagNameNS(String namespaceURI,
 186:       String localName);
 187: 
 188:   public Element getElementById(String elementId)
 189:   {
 190:     Element element = xmljGetElementById(elementId);
 191:     if (element == null)
 192:       {
 193:         TreeWalker walker = createTreeWalker(this, NodeFilter.SHOW_ELEMENT,
 194:                                              null, false);
 195:         for (Node node = walker.nextNode(); node != null;
 196:              node = walker.nextNode())
 197:           {
 198:             GnomeElement e = (GnomeElement) node;
 199:             if (e.userIdAttrs != null)
 200:               {
 201:                 for (Iterator i = e.userIdAttrs.iterator(); i.hasNext(); )
 202:                   {
 203:                     Attr attr = (Attr) i.next();
 204:                     if (attr.getNodeValue().equals(elementId))
 205:                       {
 206:                         return e;
 207:                       }
 208:                   }
 209:               }
 210:           }
 211:       }
 212:     return element;
 213:   }
 214: 
 215:   private native Element xmljGetElementById(String elementId);
 216: 
 217:   // DOM Level 3 methods
 218: 
 219:   public native String getInputEncoding();
 220: 
 221:   public native String getXmlEncoding();
 222: 
 223:   public native boolean getXmlStandalone();
 224: 
 225:   public native void setXmlStandalone(boolean xmlStandalone);
 226: 
 227:   public native String getXmlVersion();
 228: 
 229:   public native void setXmlVersion(String xmlVersion);
 230: 
 231:   public boolean getStrictErrorChecking()
 232:   {
 233:     return strictErrorChecking;
 234:   }
 235: 
 236:   public void setStrictErrorChecking(boolean strictErrorChecking)
 237:   {
 238:     this.strictErrorChecking = strictErrorChecking;
 239:   }
 240: 
 241:   public native String getDocumentURI();
 242: 
 243:   public native void setDocumentURI(String documentURI);
 244: 
 245:   public Node adoptNode(Node source)
 246:     throws DOMException
 247:   {
 248:     if (source == null || !(source instanceof GnomeNode))
 249:       {
 250:         return null;
 251:       }
 252:     Node ret = xmljAdoptNode(source);
 253:     if (source instanceof GnomeNode)
 254:       {
 255:         ((GnomeNode) source).
 256:           notifyUserDataHandlers(UserDataHandler.NODE_ADOPTED,
 257:                                  source, ret);
 258:       }
 259:     return ret;
 260:   }
 261: 
 262:   private native Node xmljAdoptNode(Node source)
 263:     throws DOMException;
 264: 
 265:   public DOMConfiguration getDomConfig()
 266:   {
 267:     return this;
 268:   }
 269: 
 270:   public void normalizeDocument()
 271:   {
 272:     normalize();
 273:   }
 274: 
 275:   public native Node renameNode(Node n, String namespaceURI,
 276:                                 String qualifiedName);
 277: 
 278:   // -- DOMConfiguration methods --
 279: 
 280:   public void setParameter(String name, Object value)
 281:     throws DOMException
 282:   {
 283:     name = name.toLowerCase();
 284:     if ("canonical-form".equals(name))
 285:       {
 286:         /* optional
 287:         canonicalForm = getBooleanValue(value);*/
 288:       }
 289:     else if ("cdata-sections".equals(name))
 290:       {
 291:         cdataSections = getBooleanValue(value);
 292:       }
 293:     else if ("check-character-normalization".equals(name))
 294:       {
 295:         /* optional
 296:         checkCharacterNormalization = getBooleanValue(value);*/
 297:       }
 298:     else if ("comments".equals(name))
 299:       {
 300:         comments = getBooleanValue(value);
 301:       }
 302:     else if ("datatype-normalization".equals(name))
 303:       {
 304:         /* optional
 305:         datatypeNormalization = getBooleanValue(value);*/
 306:       }
 307:     else if ("element-content-whitespace".equals(name))
 308:       {
 309:         /* optional
 310:         elementContentWhitespace = getBooleanValue(value);*/
 311:       }
 312:     else if ("entities".equals(name))
 313:       {
 314:         entities = getBooleanValue(value);
 315:       }
 316:     else if ("error-handler".equals(name))
 317:       {
 318:         errorHandler = (DOMErrorHandler) value;
 319:       }
 320:     else if ("infoset".equals(name))
 321:       {
 322:         if (getBooleanValue(value))
 323:           {
 324:             validateIfSchema = false;
 325:             entities = false;
 326:             datatypeNormalization = false;
 327:             cdataSections = false;
 328:             namespaceDeclarations = true;
 329:             wellFormed = true;
 330:             elementContentWhitespace = true;
 331:             comments = true;
 332:             namespaces = true;
 333:           }
 334:       }
 335:     else if ("namespaces".equals(name))
 336:       {
 337:         /* optional
 338:         namespaces = getBooleanValue(value);*/
 339:       }
 340:     else if ("namespace-declarations".equals(name))
 341:       {
 342:         namespaceDeclarations = getBooleanValue(value);
 343:       }
 344:     else if ("normalize-characters".equals(name))
 345:       {
 346:         /* optional
 347:         normalizeCharacters = getBooleanValue(value);*/
 348:       }
 349:     else if ("split-cdata-sections".equals(name))
 350:       {
 351:         splitCdataSections = getBooleanValue(value);
 352:       }
 353:     else if ("validate".equals(name))
 354:       {
 355:         /* optional
 356:         validate = getBooleanValue(value);*/
 357:       }
 358:     else if ("validate-if-schema".equals(name))
 359:       {
 360:         /* optional
 361:         validateIfSchema = getBooleanValue(value);*/
 362:       }
 363:     else if ("well-formed".equals(name))
 364:       {
 365:         /* optional
 366:         wellFormed = getBooleanValue(value);*/
 367:       }
 368:     else
 369:       {
 370:         throw new GnomeDOMException(DOMException.NOT_FOUND_ERR, name);
 371:       }
 372:   }
 373: 
 374:   public Object getParameter(String name)
 375:     throws DOMException
 376:   {
 377:     name = name.toLowerCase();
 378:     if ("canonical-form".equals(name))
 379:       {
 380:         return Boolean.valueOf(canonicalForm);
 381:       }
 382:     else if ("cdata-sections".equals(name))
 383:       {
 384:         return Boolean.valueOf(cdataSections);
 385:       }
 386:     else if ("check-character-normalization".equals(name))
 387:       {
 388:         return Boolean.valueOf(checkCharacterNormalization);
 389:       }
 390:     else if ("comments".equals(name))
 391:       {
 392:         return Boolean.valueOf(comments);
 393:       }
 394:     else if ("datatype-normalization".equals(name))
 395:       {
 396:         return Boolean.valueOf(datatypeNormalization);
 397:       }
 398:     else if ("element-content-whitespace".equals(name))
 399:       {
 400:         return Boolean.valueOf(elementContentWhitespace);
 401:       }
 402:     else if ("entities".equals(name))
 403:       {
 404:         return Boolean.valueOf(entities);
 405:       }
 406:     else if ("error-handler".equals(name))
 407:       {
 408:         return errorHandler;
 409:       }
 410:     else if ("infoset".equals(name))
 411:       {
 412:         return Boolean.valueOf(!validateIfSchema &&
 413:                                !entities &&
 414:                                !datatypeNormalization &&
 415:                                !cdataSections &&
 416:                                namespaceDeclarations &&
 417:                                wellFormed &&
 418:                                elementContentWhitespace &&
 419:                                comments &&
 420:                                namespaces);
 421:       }
 422:     else if ("namespaces".equals(name))
 423:       {
 424:         return Boolean.valueOf(namespaces);
 425:       }
 426:     else if ("namespace-declarations".equals(name))
 427:       {
 428:         return Boolean.valueOf(namespaceDeclarations);
 429:       }
 430:     else if ("normalize-characters".equals(name))
 431:       {
 432:         return Boolean.valueOf(normalizeCharacters);
 433:       }
 434:     else if ("split-cdata-sections".equals(name))
 435:       {
 436:         return Boolean.valueOf(splitCdataSections);
 437:       }
 438:     else if ("validate".equals(name))
 439:       {
 440:         return Boolean.valueOf(validate);
 441:       }
 442:     else if ("validate-if-schema".equals(name))
 443:       {
 444:         return Boolean.valueOf(validateIfSchema);
 445:       }
 446:     else if ("well-formed".equals(name))
 447:       {
 448:         return Boolean.valueOf(wellFormed);
 449:       }
 450:     else
 451:       {
 452:         throw new GnomeDOMException(DOMException.NOT_FOUND_ERR, name);
 453:       }
 454:   }
 455: 
 456:   public boolean canSetParameter(String name, Object value)
 457:   {
 458:     name = name.toLowerCase();
 459:     if ("error-handler".equals(name))
 460:       {
 461:         return (value == null || value instanceof DOMErrorHandler);
 462:       }
 463:     return ("cdata-sections".equals(name) ||
 464:             "comments".equals(name) ||
 465:             "entities".equals(name) ||
 466:             "namespace-declarations".equals(name) ||
 467:             "split-cdata-sections".equals(name));
 468:   }
 469: 
 470:   public DOMStringList getParameterNames()
 471:   {
 472:     String[] names = new String[] {
 473:       "canonical-form",
 474:       "cdata-sections",
 475:       "check-character-normalization",
 476:       "comments",
 477:       "datatype-normalization",
 478:       "element-content-whitespace",
 479:       "entities",
 480:       "error-handler",
 481:       "infoset",
 482:       "namespaces",
 483:       "namespace-declarations",
 484:       "normalize-characters",
 485:       "split-cdata-sections",
 486:       "validate",
 487:       "validate-if-schema",
 488:       "well-formed"
 489:     };
 490:     return new GnomeDOMStringList(names);
 491:   }
 492: 
 493:   private boolean getBooleanValue(Object value)
 494:   {
 495:     if (value instanceof Boolean)
 496:       {
 497:         return ((Boolean) value).booleanValue();
 498:       }
 499:     else if (value instanceof String)
 500:       {
 501:         return Boolean.valueOf ((String) value).booleanValue();
 502:       }
 503:     return false;
 504:   }
 505: 
 506:   // -- XPathEvaluator methods --
 507: 
 508:   public XPathExpression createExpression(String expression,
 509:                                           XPathNSResolver resolver)
 510:     throws XPathException, DOMException
 511:   {
 512:     return new GnomeXPathExpression(this, expression, resolver);
 513:   }
 514: 
 515:   public XPathNSResolver createNSResolver(Node nodeResolver)
 516:   {
 517:     return new GnomeXPathNSResolver(nodeResolver);
 518:   }
 519: 
 520:   public native Object evaluate(String expression,
 521:                                 Node contextNode,
 522:                                 XPathNSResolver resolver,
 523:                                 short type,
 524:                                 Object result)
 525:     throws XPathException, DOMException;
 526: 
 527:   // -- DocumentTraversal methods --
 528: 
 529:   public NodeIterator createNodeIterator(Node root,
 530:                                          int whatToShow,
 531:                                          NodeFilter filter,
 532:                                          boolean entityReferenceExpansion)
 533:     throws DOMException
 534:   {
 535:     return new DomNodeIterator(root, whatToShow, filter,
 536:                                entityReferenceExpansion, false);
 537:   }
 538: 
 539:   public TreeWalker createTreeWalker(Node root,
 540:                                     int whatToShow,
 541:                                     NodeFilter filter,
 542:                                     boolean entityReferenceExpansion)
 543:     throws DOMException
 544:   {
 545:     return new DomNodeIterator(root, whatToShow, filter,
 546:                                entityReferenceExpansion, true);
 547:   }
 548: 
 549:   // -- Debugging --
 550: 
 551:   public String toString()
 552:   {
 553:     CPStringBuilder buffer = new CPStringBuilder(getClass().getName());
 554:     buffer.append("[version=");
 555:     buffer.append(getXmlVersion());
 556:     buffer.append(",standalone=");
 557:     buffer.append(getXmlStandalone());
 558:     buffer.append("]");
 559:     return buffer.toString();
 560:   }
 561: 
 562: }