1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2001-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.impl.xs.identity;
  22 
  23 import com.sun.org.apache.xerces.internal.impl.xpath.XPathException;
  24 import com.sun.org.apache.xerces.internal.impl.xs.util.ShortListImpl;
  25 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  26 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  27 import com.sun.org.apache.xerces.internal.xs.ShortList;
  28 import com.sun.org.apache.xerces.internal.xs.XSComplexTypeDefinition;
  29 import com.sun.org.apache.xerces.internal.xs.XSConstants;
  30 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  31 
  32 /**
  33  * Schema identity constraint field.
  34  *
  35  * @xerces.internal
  36  *
  37  * @author Andy Clark, IBM
  38  */
  39 public class Field {
  40 
  41     //
  42     // Data
  43     //
  44 
  45     /** Field XPath. */
  46     protected Field.XPath fXPath;
  47 
  48 
  49     /** Identity constraint. */
  50     protected IdentityConstraint fIdentityConstraint;
  51 
  52     //
  53     // Constructors
  54     //
  55 
  56     /** Constructs a field. */
  57     public Field(Field.XPath xpath,
  58                  IdentityConstraint identityConstraint) {
  59         fXPath = xpath;
  60         fIdentityConstraint = identityConstraint;
  61     } // <init>(Field.XPath,IdentityConstraint)
  62 
  63     //
  64     // Public methods
  65     //
  66 
  67     /** Returns the field XPath. */
  68     public com.sun.org.apache.xerces.internal.impl.xpath.XPath getXPath() {
  69         return fXPath;
  70     } // getXPath():com.sun.org.apache.xerces.internal.impl.v1.schema.identity.XPath
  71 
  72     /** Returns the identity constraint. */
  73     public IdentityConstraint getIdentityConstraint() {
  74         return fIdentityConstraint;
  75     } // getIdentityConstraint():IdentityConstraint
  76 
  77     // factory method
  78 
  79     /** Creates a field matcher. */
  80     public XPathMatcher createMatcher(FieldActivator activator, ValueStore store) {
  81         return new Field.Matcher(fXPath, activator, store);
  82     } // createMatcher(ValueStore):XPathMatcher
  83 
  84     //
  85     // Object methods
  86     //
  87 
  88     /** Returns a string representation of this object. */
  89     public String toString() {
  90         return fXPath.toString();
  91     } // toString():String
  92 
  93     //
  94     // Classes
  95     //
  96 
  97     /**
  98      * Field XPath.
  99      *
 100      * @author Andy Clark, IBM
 101      */
 102     public static class XPath
 103         extends com.sun.org.apache.xerces.internal.impl.xpath.XPath {
 104 
 105         //
 106         // Constructors
 107         //
 108 
 109         /** Constructs a field XPath expression. */
 110         public XPath(String xpath,
 111                      SymbolTable symbolTable,
 112                      NamespaceContext context) throws XPathException {
 113             // NOTE: We have to prefix the field XPath with "./" in
 114             //       order to handle selectors such as "@attr" that
 115             //       select the attribute because the fields could be
 116             //       relative to the selector element. -Ac
 117             //       Unless xpath starts with a descendant node -Achille Fokoue
 118             //      ... or a / or a . - NG
 119             super(((xpath.trim().startsWith("/") ||xpath.trim().startsWith("."))?
 120                     xpath:"./"+xpath),
 121                   symbolTable, context);
 122 
 123             // verify that only one attribute is selected per branch
 124             for (int i=0;i<fLocationPaths.length;i++) {
 125                 for(int j=0; j<fLocationPaths[i].steps.length; j++) {
 126                     com.sun.org.apache.xerces.internal.impl.xpath.XPath.Axis axis =
 127                         fLocationPaths[i].steps[j].axis;
 128                     if (axis.type == XPath.Axis.ATTRIBUTE &&
 129                             (j < fLocationPaths[i].steps.length-1)) {
 130                         throw new XPathException("c-fields-xpaths");
 131                     }
 132                 }
 133             }
 134         } // <init>(String,SymbolTable,NamespacesContext)
 135 
 136     } // class XPath
 137 
 138     /**
 139      * Field matcher.
 140      *
 141      * @author Andy Clark, IBM
 142      */
 143     protected class Matcher
 144         extends XPathMatcher {
 145 
 146         //
 147         // Data
 148         //
 149 
 150         /** Field activator. */
 151         protected FieldActivator fFieldActivator;
 152 
 153         /** Value store for data values. */
 154         protected ValueStore fStore;
 155 
 156         //
 157         // Constructors
 158         //
 159 
 160         /** Constructs a field matcher. */
 161         public Matcher(Field.XPath xpath, FieldActivator activator, ValueStore store) {
 162             super(xpath);
 163             fFieldActivator = activator;
 164             fStore = store;
 165         } // <init>(Field.XPath,ValueStore)
 166 
 167         //
 168         // XPathHandler methods
 169         //
 170 
 171         /**
 172          * This method is called when the XPath handler matches the
 173          * XPath expression.
 174          */
 175         protected void matched(Object actualValue, short valueType, ShortList itemValueType, boolean isNil) {
 176             super.matched(actualValue, valueType, itemValueType, isNil);
 177             if(isNil && (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY)) {
 178                 String code = "KeyMatchesNillable";
 179                 fStore.reportError(code,
 180                     new Object[]{fIdentityConstraint.getElementName(), fIdentityConstraint.getIdentityConstraintName()});
 181             }
 182             fStore.addValue(Field.this, actualValue, convertToPrimitiveKind(valueType), convertToPrimitiveKind(itemValueType));
 183             // once we've stored the value for this field, we set the mayMatch
 184             // member to false so that, in the same scope, we don't match any more
 185             // values (and throw an error instead).
 186             fFieldActivator.setMayMatch(Field.this, Boolean.FALSE);
 187         } // matched(String)
 188 
 189         private short convertToPrimitiveKind(short valueType) {
 190             /** Primitive datatypes. */
 191             if (valueType <= XSConstants.NOTATION_DT) {
 192                 return valueType;
 193             }
 194             /** Types derived from string. */
 195             if (valueType <= XSConstants.ENTITY_DT) {
 196                 return XSConstants.STRING_DT;
 197             }
 198             /** Types derived from decimal. */
 199             if (valueType <= XSConstants.POSITIVEINTEGER_DT) {
 200                 return XSConstants.DECIMAL_DT;
 201             }
 202             /** Other types. */
 203             return valueType;
 204         }
 205 
 206         private ShortList convertToPrimitiveKind(ShortList itemValueType) {
 207             if (itemValueType != null) {
 208                 int i;
 209                 final int length = itemValueType.getLength();
 210                 for (i = 0; i < length; ++i) {
 211                     short type = itemValueType.item(i);
 212                     if (type != convertToPrimitiveKind(type)) {
 213                         break;
 214                     }
 215                 }
 216                 if (i != length) {
 217                     final short [] arr = new short[length];
 218                     for (int j = 0; j < i; ++j) {
 219                         arr[j] = itemValueType.item(j);
 220                     }
 221                     for(; i < length; ++i) {
 222                         arr[i] = convertToPrimitiveKind(itemValueType.item(i));
 223                     }
 224                     return new ShortListImpl(arr, arr.length);
 225                 }
 226             }
 227             return itemValueType;
 228         }
 229 
 230         protected void handleContent(XSTypeDefinition type, boolean nillable, Object actualValue, short valueType, ShortList itemValueType) {
 231             if (type == null ||
 232                type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE &&
 233                ((XSComplexTypeDefinition) type).getContentType()
 234                 != XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
 235 
 236                     // the content must be simpleType content
 237                     fStore.reportError( "cvc-id.3", new Object[] {
 238                             fIdentityConstraint.getName(),
 239                             fIdentityConstraint.getElementName()});
 240 
 241             }
 242             fMatchedString = actualValue;
 243             matched(fMatchedString, valueType, itemValueType, nillable);
 244         } // handleContent(XSElementDecl, String)
 245 
 246     } // class Matcher
 247 
 248 } // class Field