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