Clover coverage report - JBind Project
Coverage timestamp: Fr Mai 28 2004 11:17:36 CEST
file stats: LOC: 333   Methods: 11
NCLOC: 269   Classes: 2
This license of Clover is provided to support the development of JBind only. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover.
 
 Source file Conditionals Statements Methods TOTAL
DataBuilder.java 84,6% 90,6% 100% 89,1%
 1   
 /*
 2   
  * JBind
 3   
  *
 4   
  * Copyright (c) by Stefan Wachter. All rights reserved.
 5   
  *
 6   
  * Usage, modification, and redistribution is subject to license terms that are
 7   
  * available at 'http://www.jbind.org'. The JBind license is like the
 8   
  * 'Apache Software License V 1.1'.
 9   
  */
 10   
 package org.jbind.xml.instance.builder;
 11   
 
 12   
 import java.net.MalformedURLException;
 13   
 import java.net.URL;
 14   
 import java.util.Enumeration;
 15   
 import java.util.Iterator;
 16   
 import java.util.StringTokenizer;
 17   
 
 18   
 import org.jbind.util.collection.UnsynchronizedStack;
 19   
 import org.jbind.xml.Config;
 20   
 import org.jbind.xml.base.ILocation;
 21   
 import org.jbind.xml.base.INamespaces;
 22   
 import org.jbind.xml.base.IQName;
 23   
 import org.jbind.xml.base.IRef;
 24   
 import org.jbind.xml.base.ISymbolspaces;
 25   
 import org.jbind.xml.base.QName;
 26   
 import org.jbind.xml.base.Ref;
 27   
 import org.jbind.xml.base.StringUtil;
 28   
 import org.jbind.xml.base.WhiteSpaceProcessing;
 29   
 import org.jbind.xml.core.bridge.IAttributeImpl;
 30   
 import org.jbind.xml.core.bridge.IDataImpl;
 31   
 import org.jbind.xml.core.bridge.IDefaultAttrCreator;
 32   
 import org.jbind.xml.core.bridge.IElementImpl;
 33   
 import org.jbind.xml.core.bridge.IImplContainer;
 34   
 import org.jbind.xml.core.cmp.ISchema;
 35   
 import org.jbind.xml.core.cmp.IUseStateIterator;
 36   
 import org.jbind.xml.core.content.IAttrDesc;
 37   
 import org.jbind.xml.core.content.IElemDesc;
 38   
 import org.jbind.xml.core.content.IElemRefOrDecl;
 39   
 import org.jbind.xml.core.data.IAnyTypeData;
 40   
 import org.jbind.xml.core.type.IAnyType;
 41   
 import org.jbind.xml.facade.JBindFacade;
 42   
 import org.jbind.xml.msg.IConstraintViolations;
 43   
 import org.jbind.xml.msg.XmlException;
 44   
 import org.jbind.xml.msg.XmlMessages;
 45   
 import org.jbind.xml.schema.cmp.Schemas;
 46   
 import org.jbind.xml.schema.instantiation.ISchemaReader;
 47   
 
 48   
 public class DataBuilder implements IDataBuilder {
 49   
 
 50   
   private static class BuildInfo {
 51   
 
 52   
     public IElemDesc elemDesc;
 53   
     public IAnyType overloadingType;
 54   
     public IUseStateIterator useStateIterator;
 55   
     public IElemRefOrDecl substitutionHead;
 56   
 
 57  2420
     public BuildInfo(IElemDesc aDesc, IAnyType anOverloadingType, IElemRefOrDecl aSubstitutionHead, IUseStateIterator aUseStateIterator) {
 58  2420
       elemDesc = aDesc;
 59  2420
       overloadingType = anOverloadingType;
 60  2420
       substitutionHead = aSubstitutionHead;
 61  2420
       useStateIterator = aUseStateIterator;
 62   
     }
 63   
   }
 64   
 
 65   
   /**
 66   
    * Stores build infos.
 67   
    */
 68   
   private UnsynchronizedStack myStack = null;
 69   
   private int mySkipped = 0;
 70   
   private int myNil = 0;
 71   
 
 72   
   private boolean myUseBuiltInClassesOnly;
 73   
 
 74  222
   public DataBuilder(boolean aUseBuiltInClassesOnly) {
 75  222
     myUseBuiltInClassesOnly = aUseBuiltInClassesOnly;
 76   
   }
 77   
 
 78  223
   public void initialize() {
 79  223
     myStack = new UnsynchronizedStack();
 80  223
     mySkipped = 0;
 81   
   }
 82   
 
 83  2420
   private void push(BuildInfo anItem) {
 84  2420
     myStack.push(anItem);
 85   
   }
 86  6110
   private BuildInfo peek() {
 87  6110
     return (BuildInfo)myStack.peek();
 88   
   }
 89  2420
   private BuildInfo pop() {
 90  2420
     return (BuildInfo)myStack.pop();
 91   
   }
 92  6333
   private boolean stackEmpty() {
 93  6333
     return myStack.size() == 0;
 94   
   }
 95   
 
 96  2739
   public void startElement(IElementImpl anElement, IConstraintViolations aViolations) throws XmlException {
 97  2739
     if (myNil > 0) {
 98  1
       aViolations.add(XmlMessages.nilledElementContainedData(anElement));
 99  1
       myNil++;
 100  1
       return;
 101   
     }
 102   
 
 103  2738
     if (mySkipped > 0) {
 104  22
       mySkipped++;
 105  22
       return;
 106   
     }
 107   
 
 108   
     //
 109   
     // Treat the xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes.
 110   
     //
 111   
 
 112  2716
     IAttributeImpl xsiSchemaLocation = anElement.getAttributeImpl(INamespaces.XML_SCHEMA_INSTANCE, "schemaLocation");
 113  2716
     if (null != xsiSchemaLocation) {
 114  34
       for (Enumeration e = new StringTokenizer(xsiSchemaLocation.getTextContent());
 115  68
               e.hasMoreElements(); ) {
 116  34
         String namespace = (String)e.nextElement();
 117  34
         if (!e.hasMoreElements()) {
 118  0
           aViolations.add(XmlMessages.missingSchemaLocation(namespace, anElement));
 119   
         } else {
 120  34
           String stringUrl = (String)e.nextElement();
 121  34
           if (null != Schemas.getInstance().getSchema(namespace)) {
 122  33
             continue;
 123   
           }
 124  1
           readSchema(anElement, namespace, stringUrl, aViolations);
 125   
         }
 126   
       }
 127   
     }
 128  2716
     IAttributeImpl xsiNoNamespaceSchemaLocation = anElement.getAttributeImpl(INamespaces.XML_SCHEMA_INSTANCE, "noNamespaceSchemaLocation");
 129  2716
     if (null != xsiNoNamespaceSchemaLocation) {
 130  4
       if (null == Schemas.getInstance().getSchema(INamespaces.NO)) {
 131  0
         readSchema(anElement, INamespaces.NO, xsiNoNamespaceSchemaLocation.getTextContent(), aViolations);
 132   
       }
 133   
     }
 134   
 
 135  2716
     IAnyType overloadingType = null;
 136   
 
 137  2716
     IAttributeImpl xsiTypeImpl = anElement.getAttributeImpl(INamespaces.XML_SCHEMA_INSTANCE, "type");
 138  2716
     if (null != xsiTypeImpl) {
 139  149
       String overloadingTypeName = xsiTypeImpl.getTextContent();
 140  149
       IQName qName = QName.create(overloadingTypeName, anElement.getPrefixToNamespaceMapping());
 141  149
       if (null == qName) {
 142  0
         throw new XmlException(XmlMessages.invalidQName(overloadingTypeName, anElement));
 143   
       }
 144  149
       IRef overloadingTypeRef = new Ref(qName.getNamespace(), ISymbolspaces.TYPE, qName.getLocalPart());
 145  149
       overloadingType = (IAnyType)Schemas.getInstance().getComponent(overloadingTypeRef);
 146  149
       if (null == overloadingType) {
 147  2
         throw new XmlException(XmlMessages.unknownOverloadingType(overloadingTypeRef, anElement));
 148   
       }
 149   
     }
 150   
 
 151  2714
     IElemDesc elementDecl = null;
 152  2714
     IElemRefOrDecl substitutionHead = null;
 153   
 
 154  2714
     String elmNamespace = anElement.getNamespace();
 155  2714
     String elmName = anElement.getPartName();
 156   
 
 157  2714
     ISchema schema = Schemas.getInstance().getSchema(elmNamespace);
 158  2714
     if (null == schema) {
 159  313
       String url = Config.instance.resolveUri(elmNamespace);
 160  313
       if (null != url) {
 161  0
         readSchema(anElement, elmNamespace, url.toString(), aViolations);
 162   
       }
 163   
     }
 164   
 
 165  2714
     if (stackEmpty()) {
 166  223
       IRef ref = new Ref(elmNamespace, ISymbolspaces.ELEMENT, elmName);
 167  223
       elementDecl = (IElemDesc)Schemas.getInstance().getComponent(ref);
 168  223
       if (null == elementDecl) {
 169  0
         throw new XmlException(XmlMessages.unknownRootElement(ref, anElement));
 170   
       }
 171   
 
 172   
     } else {
 173  2491
       BuildInfo parentInfo = peek();
 174  2491
       elementDecl = parentInfo.useStateIterator.getNextElemDesc(elmNamespace, elmName, overloadingType, anElement);
 175  2459
       substitutionHead = parentInfo.useStateIterator.getSubstitutionHead();
 176   
 
 177   
     }
 178   
 
 179  2682
     if (null == elementDecl) {
 180  261
       mySkipped = 1;
 181  261
       return;
 182   
     }
 183   
 
 184  2421
     if (elementDecl.isAbstract()) {
 185  1
       IRef ref = new Ref(anElement.getNamespace(), ISymbolspaces.ELEMENT, anElement.getPartName());
 186  1
       throw new XmlException(XmlMessages.triedToInstantiateAbstractElement(ref, anElement));
 187   
     }
 188   
 
 189  2420
     anElement.setDefaultTextContent(elementDecl.getDefaultTextContent());
 190   
 
 191  2420
     IAnyType declaredType = elementDecl.getType();
 192  2420
     IAnyType elementType = (null != overloadingType) ? overloadingType : declaredType;
 193   
 
 194   
     // Create data objects for the attributes
 195  2420
     for (Iterator i = anElement.iterAttributeImpls(); i.hasNext(); ) {
 196  1700
       IAttributeImpl ai = (IAttributeImpl)i.next();
 197  1700
       String namespace = ai.getNamespace();
 198  1700
       if (INamespaces.XML_SCHEMA_INSTANCE.equals(ai.getNamespace())) {
 199  189
         continue;
 200   
       }
 201   
 
 202  1511
       if (null == Schemas.getInstance().getSchema(namespace)) {
 203  1445
         String url = Config.instance.resolveUri(namespace);
 204  1445
         if (null != url) {
 205  0
           readSchema(ai, namespace, url.toString(), aViolations);
 206   
         }
 207   
       }
 208   
 
 209   
 
 210  1511
       String name = ai.getPartName();
 211  1511
       try {
 212  1511
         IAttrDesc desc = elementType.getAttrDesc(namespace, name, anElement);
 213   
         // skippable attributes wildcards are not returned.
 214  1502
         if (null != desc) {
 215  1492
           IAnyTypeData data = desc.createData(ai, null);
 216  1472
           ai.setData(data);
 217   
         }
 218   
       } catch (XmlException e) {
 219  29
         aViolations.add(e.getXmlMessage());
 220   
       }
 221   
     }
 222   
 
 223  2420
     if (elementType.isComplex()) {
 224  1987
       anElement.setDefaultAttrCreator((IDefaultAttrCreator)elementType);
 225   
     }
 226   
 
 227  2420
     boolean isNil = false;
 228  2420
     IAttributeImpl xsiNilImpl = anElement.getAttributeImpl(INamespaces.XML_SCHEMA_INSTANCE, "nil");
 229  2420
     if (null != xsiNilImpl) {
 230  4
       if (!elementDecl.isNillable()) {
 231  0
         aViolations.add(XmlMessages.nilAttributeNotAllowed(anElement));
 232   
       }
 233  4
       String nilString = xsiNilImpl.getTextContent();
 234  4
       if ("false".equals(nilString)) {
 235   
         // nothing
 236  0
         isNil = false;// JIKES because of a bug in jikes there must be a statement here
 237  4
       } else if ("true".equals(nilString)) {
 238  4
         isNil = true;
 239  4
         if (null != elementDecl.getFixed()) {
 240  0
           aViolations.add(XmlMessages.nilledElementMustNotHaveFixedValue(anElement));
 241   
         }
 242   
       } else {
 243  0
         aViolations.add(XmlMessages.invalidValueForNilAttribute(nilString, anElement));
 244   
       }
 245   
     }
 246   
 
 247  2420
     if (isNil) {
 248  4
       myNil++;
 249   
     }
 250   
 
 251  2420
     IUseStateIterator useIterator = elementType.getContentModel().createUseIterator();
 252  2420
     BuildInfo buildInfo = new BuildInfo(elementDecl, overloadingType, substitutionHead, useIterator);
 253  2420
     push(buildInfo);
 254   
 
 255   
   }
 256   
 
 257   
   /**
 258   
    * Creates a data object for the element. The data object can only be created after
 259   
    * the element ended because in case of an element that has a union type the actual type of
 260   
    * the data object to be instantiated depends on the textual content of the element.
 261   
    */
 262  2704
   public void endElement(IElementImpl anElement, ILocation aLocation, IConstraintViolations aViolations) throws XmlException {
 263  2704
     if (myNil > 1) {
 264  1
       myNil--;
 265  1
       return;
 266   
     }
 267  2703
     if (mySkipped > 0) {
 268  283
       mySkipped--;
 269  283
       return;
 270   
     }
 271  2420
     BuildInfo buildInfo = pop();
 272  2420
     IAnyTypeData data = null;
 273  2420
     if (myNil == 0) {
 274  2416
       buildInfo.useStateIterator.isValidEnd(aLocation);
 275  2394
       data = (IAnyTypeData)buildInfo.elemDesc.createData(anElement, buildInfo.overloadingType);
 276  2338
       data.setSubstitutionHead_(buildInfo.substitutionHead);
 277   
     } else {
 278  4
       myNil--;
 279  4
       if (anElement.iterChildren().hasNext()) {
 280  3
         IAnyType t = (null != buildInfo.overloadingType) ? buildInfo.overloadingType : buildInfo.elemDesc.getType();
 281  3
         WhiteSpaceProcessing wsp = t.getConstraints().getWhiteSpaceProcessing();
 282  3
         String tc = wsp.process(anElement.getTextContent());
 283  3
         if ((null != tc) && !"".equals(tc)) {
 284  1
           aViolations.add(XmlMessages.nilledElementContainedData(anElement));
 285   
         }
 286   
       }
 287  4
       data = (IAnyTypeData)buildInfo.elemDesc.createUncheckedData(anElement, buildInfo.overloadingType);
 288   
     }
 289  2342
     anElement.setData(data);
 290   
   }
 291   
 
 292  3665
   public void signalText(IImplContainer aContainer, String aText, ILocation aLocation, IConstraintViolations aViolations) {
 293  3665
     boolean canTakeText = true;
 294  3665
     if ((mySkipped == 0) && !stackEmpty()) {
 295  3619
       BuildInfo bi = peek();
 296  3619
       IAnyType type = (null != bi.overloadingType) ? bi.overloadingType : bi.elemDesc.getType();
 297  3619
       canTakeText = type.getContentModel().canContainText();
 298   
     }
 299  3665
     if (canTakeText) {
 300  679
       aContainer.addText(aText, aLocation);
 301   
     } else {
 302  2986
       if (!StringUtil.isWhiteSpace(aText)) {
 303  5
         aViolations.add(XmlMessages.unexpectedTextualContent(aText, aLocation));
 304   
       }
 305   
     }
 306   
   }
 307   
 
 308  1
   private void readSchema(IDataImpl aDataImpl, String aNamespace, String aUrl, IConstraintViolations aViolations) {
 309  1
     URL baseUrl = aDataImpl.getLocation().getExpandedSystemId();
 310  1
     try {
 311  1
       URL url = null;
 312  1
       String resolvedNamespace = Config.instance.resolveUri(aNamespace);
 313  1
       if (null != resolvedNamespace) {
 314  0
         url = new URL(resolvedNamespace);
 315   
       } else {
 316  1
         url = (null != baseUrl) ? new URL(baseUrl, aUrl) : new URL(aUrl);
 317   
       }
 318  1
       ISchemaReader reader = JBindFacade.createSchemaReader();
 319  1
       ISchema schema = reader.readSchema(url, myUseBuiltInClassesOnly, null);
 320  1
       if (aNamespace.equals(schema.getNamespace())) {
 321  1
         Schemas.getInstance().setSchema(schema);
 322   
       } else {
 323  0
         aViolations.add(XmlMessages.invalidNamespaceInReferencedSchema(aNamespace, schema.getNamespace(), aDataImpl));
 324   
       }
 325   
     } catch (XmlException e) {
 326  0
       aViolations.add(e.getXmlMessage());
 327   
     } catch (MalformedURLException e) {
 328  0
       aViolations.add(XmlMessages.invalidSchemaUrl(aUrl, aDataImpl));
 329   
     }
 330   
   }
 331   
 
 332   
 }
 333