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