View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001, 2002,2004,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.util.SymbolTable;
25  import com.sun.org.apache.xerces.internal.util.XMLChar;
26  import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
27  import com.sun.org.apache.xerces.internal.xni.QName;
28  import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
29  import com.sun.org.apache.xerces.internal.xs.ShortList;
30  import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
31  
32  /**
33   * Schema identity constraint selector.
34   *
35   * @xerces.internal
36   *
37   * @author Andy Clark, IBM
38   * @version $Id: Selector.java,v 1.7 2010-11-01 04:39:57 joehw Exp $
39   */
40  public 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      * @version $Id: Selector.java,v 1.7 2010-11-01 04:39:57 joehw Exp $
110      */
111     public static class XPath
112     extends com.sun.org.apache.xerces.internal.impl.xpath.XPath {
113 
114         //
115         // Constructors
116         //
117 
118         /** Constructs a selector XPath expression. */
119         public XPath(String xpath, SymbolTable symbolTable,
120                      NamespaceContext context) throws XPathException {
121             super(normalize(xpath), symbolTable, context);
122             // verify that an attribute is not selected
123             for (int i=0;i<fLocationPaths.length;i++) {
124                 com.sun.org.apache.xerces.internal.impl.xpath.XPath.Axis axis =
125                 fLocationPaths[i].steps[fLocationPaths[i].steps.length-1].axis;
126                 if (axis.type == XPath.Axis.ATTRIBUTE) {
127                     throw new XPathException("c-selector-xpath");
128                 }
129             }
130 
131         } // <init>(String,SymbolTable,NamespacesScope)
132 
133         private static String normalize(String xpath) {
134             // NOTE: We have to prefix the selector XPath with "./" in
135             //       order to handle selectors such as "." that select
136             //       the element container because the fields could be
137             //       relative to that element. -Ac
138             //       Unless xpath starts with a descendant node -Achille Fokoue
139             //      ... or a '.' or a '/' - NG
140             //  And we also need to prefix exprs to the right of | with ./ - NG
141             StringBuffer modifiedXPath = new StringBuffer(xpath.length()+5);
142             int unionIndex = -1;
143             do {
144                 if(!(XMLChar.trim(xpath).startsWith("/") || XMLChar.trim(xpath).startsWith("."))) {
145                     modifiedXPath.append("./");
146                 }
147                 unionIndex = xpath.indexOf('|');
148                 if(unionIndex == -1) {
149                     modifiedXPath.append(xpath);
150                     break;
151                 }
152                 modifiedXPath.append(xpath.substring(0,unionIndex+1));
153                 xpath = xpath.substring(unionIndex+1, xpath.length());
154             } while(true);
155             return modifiedXPath.toString();
156         }
157 
158     } // class Selector.XPath
159 
160     /**
161      * Selector matcher.
162      *
163      * @author Andy Clark, IBM
164      */
165     public class Matcher
166     extends XPathMatcher {
167 
168         //
169         // Data
170         //
171 
172         /** Field activator. */
173         protected final FieldActivator fFieldActivator;
174 
175         /** Initial depth in the document at which this matcher was created. */
176         protected final int fInitialDepth;
177 
178         /** Element depth. */
179         protected int fElementDepth;
180 
181         /** Depth at match. */
182         protected int fMatchedDepth;
183 
184         //
185         // Constructors
186         //
187 
188         /** Constructs a selector matcher. */
189         public Matcher(Selector.XPath xpath, FieldActivator activator,
190                 int initialDepth) {
191             super(xpath);
192             fFieldActivator = activator;
193             fInitialDepth = initialDepth;
194         } // <init>(Selector.XPath,FieldActivator)
195 
196         //
197         // XMLDocumentFragmentHandler methods
198         //
199 
200         public void startDocumentFragment(){
201             super.startDocumentFragment();
202             fElementDepth = 0;
203             fMatchedDepth = -1;
204         } // startDocumentFragment()
205 
206         /**
207          * The start of an element. If the document specifies the start element
208          * by using an empty tag, then the startElement method will immediately
209          * be followed by the endElement method, with no intervening methods.
210          *
211          * @param element    The name of the element.
212          * @param attributes The element attributes.
213          *
214          */
215         public void startElement(QName element, XMLAttributes attributes) {
216             super.startElement(element, attributes);
217             fElementDepth++;
218             // activate the fields, if selector is matched
219             //int matched = isMatched();
220 
221             if (isMatched()) {
222 /*            (fMatchedDepth == -1 && ((matched & MATCHED) == MATCHED)) ||
223                     ((matched & MATCHED_DESCENDANT) == MATCHED_DESCENDANT)) { */
224                 fMatchedDepth = fElementDepth;
225                 fFieldActivator.startValueScopeFor(fIdentityConstraint, fInitialDepth);
226                 int count = fIdentityConstraint.getFieldCount();
227                 for (int i = 0; i < count; i++) {
228                     Field field = fIdentityConstraint.getFieldAt(i);
229                     XPathMatcher matcher = fFieldActivator.activateField(field, fInitialDepth);
230                     matcher.startElement(element, attributes);
231                 }
232             }
233 
234         } // startElement(QName,XMLAttrList,int)
235 
236         public void endElement(QName element, XSTypeDefinition type, boolean nillable, Object actualValue, short valueType, ShortList itemValueType) {
237             super.endElement(element, type, nillable, actualValue, valueType, itemValueType);
238             if (fElementDepth-- == fMatchedDepth) {
239                 fMatchedDepth = -1;
240                 fFieldActivator.endValueScopeFor(fIdentityConstraint, fInitialDepth);
241             }
242         }
243 
244         /** Returns the identity constraint. */
245         public IdentityConstraint getIdentityConstraint() {
246             return fIdentityConstraint;
247         } // getIdentityConstraint():IdentityConstraint
248 
249         /** get the initial depth at which this selector matched. */
250         public int getInitialDepth() {
251             return fInitialDepth;
252         } // getInitialDepth():  int
253 
254 
255     } // class Matcher
256 
257 } // class Selector