1/* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5/* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22package com.sun.org.apache.xerces.internal.impl.xs.identity; 23 24import com.sun.org.apache.xerces.internal.impl.xpath.XPathException; 25import com.sun.org.apache.xerces.internal.util.SymbolTable; 26import com.sun.org.apache.xerces.internal.util.XMLChar; 27import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 28import com.sun.org.apache.xerces.internal.xni.QName; 29import com.sun.org.apache.xerces.internal.xni.XMLAttributes; 30import com.sun.org.apache.xerces.internal.xs.ShortList; 31import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; 32 33/** 34 * Schema identity constraint selector. 35 * 36 * @xerces.internal 37 * 38 * @author Andy Clark, IBM 39 */ 40public class Selector { 41 42 // 43 // Data 44 // 45 46 /** XPath. */ 47 protected final Selector.XPath fXPath; 48 49 /** Identity constraint. */ 50 protected final IdentityConstraint fIdentityConstraint; 51 52 // the Identity constraint we're the matcher for. Only 53 // used for selectors! 54 protected IdentityConstraint fIDConstraint; 55 56 // 57 // Constructors 58 // 59 60 /** Constructs a selector. */ 61 public Selector(Selector.XPath xpath, 62 IdentityConstraint identityConstraint) { 63 fXPath = xpath; 64 fIdentityConstraint = identityConstraint; 65 } // <init>(Selector.XPath,IdentityConstraint) 66 67 // 68 // Public methods 69 // 70 71 /** Returns the selector XPath. */ 72 public com.sun.org.apache.xerces.internal.impl.xpath.XPath getXPath() { 73 return fXPath; 74 } // getXPath():com.sun.org.apache.xerces.internal.v1.schema.identity.XPath 75 76 /** Returns the identity constraint. */ 77 public IdentityConstraint getIDConstraint() { 78 return fIdentityConstraint; 79 } // getIDConstraint():IdentityConstraint 80 81 // factory method 82 83 /** Creates a selector matcher. 84 * @param activator The activator for this selector's fields. 85 * @param initialDepth The depth in the document at which this matcher began its life; 86 * used in correctly handling recursive elements. 87 */ 88 public XPathMatcher createMatcher(FieldActivator activator, int initialDepth) { 89 return new Selector.Matcher(fXPath, activator, initialDepth); 90 } // createMatcher(FieldActivator):XPathMatcher 91 92 // 93 // Object methods 94 // 95 96 /** Returns a string representation of this object. */ 97 public String toString() { 98 return fXPath.toString(); 99 } // toString():String 100 101 // 102 // Classes 103 // 104 105 /** 106 * Schema identity constraint selector XPath expression. 107 * 108 * @author Andy Clark, IBM 109 */ 110 public static class XPath 111 extends com.sun.org.apache.xerces.internal.impl.xpath.XPath { 112 113 // 114 // Constructors 115 // 116 117 /** Constructs a selector XPath expression. */ 118 public XPath(String xpath, SymbolTable symbolTable, 119 NamespaceContext context) throws XPathException { 120 super(normalize(xpath), symbolTable, context); 121 // verify that an attribute is not selected 122 for (int i=0;i<fLocationPaths.length;i++) { 123 com.sun.org.apache.xerces.internal.impl.xpath.XPath.Axis axis = 124 fLocationPaths[i].steps[fLocationPaths[i].steps.length-1].axis; 125 if (axis.type == XPath.Axis.ATTRIBUTE) { 126 throw new XPathException("c-selector-xpath"); 127 } 128 } 129 130 } // <init>(String,SymbolTable,NamespacesScope) 131 132 private static String normalize(String xpath) { 133 // NOTE: We have to prefix the selector XPath with "./" in 134 // order to handle selectors such as "." that select 135 // the element container because the fields could be 136 // relative to that element. -Ac 137 // Unless xpath starts with a descendant node -Achille Fokoue 138 // ... or a '.' or a '/' - NG 139 // And we also need to prefix exprs to the right of | with ./ - NG 140 StringBuffer modifiedXPath = new StringBuffer(xpath.length()+5); 141 int unionIndex = -1; 142 do { 143 if(!(XMLChar.trim(xpath).startsWith("/") || XMLChar.trim(xpath).startsWith("."))) { 144 modifiedXPath.append("./"); 145 } 146 unionIndex = xpath.indexOf('|'); 147 if(unionIndex == -1) { 148 modifiedXPath.append(xpath); 149 break; 150 } 151 modifiedXPath.append(xpath.substring(0,unionIndex+1)); 152 xpath = xpath.substring(unionIndex+1, xpath.length()); 153 } while(true); 154 return modifiedXPath.toString(); 155 } 156 157 } // class Selector.XPath 158 159 /** 160 * Selector matcher. 161 * 162 * @author Andy Clark, IBM 163 */ 164 public class Matcher 165 extends XPathMatcher { 166 167 // 168 // Data 169 // 170 171 /** Field activator. */ 172 protected final FieldActivator fFieldActivator; 173 174 /** Initial depth in the document at which this matcher was created. */ 175 protected final int fInitialDepth; 176 177 /** Element depth. */ 178 protected int fElementDepth; 179 180 /** Depth at match. */ 181 protected int fMatchedDepth; 182 183 // 184 // Constructors 185 // 186 187 /** Constructs a selector matcher. */ 188 public Matcher(Selector.XPath xpath, FieldActivator activator, 189 int initialDepth) { 190 super(xpath); 191 fFieldActivator = activator; 192 fInitialDepth = initialDepth; 193 } // <init>(Selector.XPath,FieldActivator) 194 195 // 196 // XMLDocumentFragmentHandler methods 197 // 198 199 public void startDocumentFragment(){ 200 super.startDocumentFragment(); 201 fElementDepth = 0; 202 fMatchedDepth = -1; 203 } // startDocumentFragment() 204 205 /** 206 * The start of an element. If the document specifies the start element 207 * by using an empty tag, then the startElement method will immediately 208 * be followed by the endElement method, with no intervening methods. 209 * 210 * @param element The name of the element. 211 * @param attributes The element attributes. 212 * 213 */ 214 public void startElement(QName element, XMLAttributes attributes) { 215 super.startElement(element, attributes); 216 fElementDepth++; 217 // activate the fields, if selector is matched 218 //int matched = isMatched(); 219 220 if (isMatched()) { 221/* (fMatchedDepth == -1 && ((matched & MATCHED) == MATCHED)) || 222 ((matched & MATCHED_DESCENDANT) == MATCHED_DESCENDANT)) { */ 223 fMatchedDepth = fElementDepth; 224 fFieldActivator.startValueScopeFor(fIdentityConstraint, fInitialDepth); 225 int count = fIdentityConstraint.getFieldCount(); 226 for (int i = 0; i < count; i++) { 227 Field field = fIdentityConstraint.getFieldAt(i); 228 XPathMatcher matcher = fFieldActivator.activateField(field, fInitialDepth); 229 matcher.startElement(element, attributes); 230 } 231 } 232 233 } // startElement(QName,XMLAttrList,int) 234 235 public void endElement(QName element, XSTypeDefinition type, boolean nillable, Object actualValue, short valueType, ShortList itemValueType) { 236 super.endElement(element, type, nillable, actualValue, valueType, itemValueType); 237 if (fElementDepth-- == fMatchedDepth) { 238 fMatchedDepth = -1; 239 fFieldActivator.endValueScopeFor(fIdentityConstraint, fInitialDepth); 240 } 241 } 242 243 /** Returns the identity constraint. */ 244 public IdentityConstraint getIdentityConstraint() { 245 return fIdentityConstraint; 246 } // getIdentityConstraint():IdentityConstraint 247 248 /** get the initial depth at which this selector matched. */ 249 public int getInitialDepth() { 250 return fInitialDepth; 251 } // getInitialDepth(): int 252 253 254 } // class Matcher 255 256} // class Selector 257