content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * reserved comment block
   * DO NOT REMOVE OR ALTER!
   */
  /*
   * Copyright 2001-2005 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package jaxp.sun.org.apache.xerces.internal.impl.xs.identity;
  
  import jaxp.sun.org.apache.xerces.internal.impl.xpath.XPathException;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.util.ShortListImpl;
  import jaxp.sun.org.apache.xerces.internal.util.SymbolTable;
  import jaxp.sun.org.apache.xerces.internal.xni.NamespaceContext;
  import jaxp.sun.org.apache.xerces.internal.xs.ShortList;
  import jaxp.sun.org.apache.xerces.internal.xs.XSComplexTypeDefinition;
  import jaxp.sun.org.apache.xerces.internal.xs.XSConstants;
  import jaxp.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  
  /**
   * Schema identity constraint field.
   *
   * @xerces.internal
   *
   * @author Andy Clark, IBM
   * @version $Id: Field.java,v 1.6 2010-11-01 04:39:57 joehw Exp $
   */
  public class Field {
  
      //
      // Data
      //
  
      /** Field XPath. */
      protected Field.XPath fXPath;
  
  
      /** Identity constraint. */
      protected IdentityConstraint fIdentityConstraint;
  
      //
      // Constructors
      //
  
      /** Constructs a field. */
      public Field(Field.XPath xpath,
                   IdentityConstraint identityConstraint) {
          fXPath = xpath;
          fIdentityConstraint = identityConstraint;
      } // <init>(Field.XPath,IdentityConstraint)
  
      //
      // Public methods
      //
  
      /** Returns the field XPath. */
      public jaxp.sun.org.apache.xerces.internal.impl.xpath.XPath getXPath() {
          return fXPath;
      } // getXPath():com.sun.org.apache.xerces.internal.impl.v1.schema.identity.XPath
  
      /** Returns the identity constraint. */
      public IdentityConstraint getIdentityConstraint() {
          return fIdentityConstraint;
      } // getIdentityConstraint():IdentityConstraint
  
      // factory method
  
      /** Creates a field matcher. */
      public XPathMatcher createMatcher(FieldActivator activator, ValueStore store) {
          return new Field.Matcher(fXPath, activator, store);
      } // createMatcher(ValueStore):XPathMatcher
  
      //
      // Object methods
      //
  
      /** Returns a string representation of this object. */
      public String toString() {
          return fXPath.toString();
      } // toString():String
  
      //
      // Classes
      //
  
      /**
       * Field XPath.
       *
       * @author Andy Clark, IBM
       */
      public static class XPath
          extends jaxp.sun.org.apache.xerces.internal.impl.xpath.XPath {
  
          //
          // Constructors
          //
  
          /** Constructs a field XPath expression. */
          public XPath(String xpath,
                       SymbolTable symbolTable,
                       NamespaceContext context) throws XPathException {
              // NOTE: We have to prefix the field XPath with "./" in
              //       order to handle selectors such as "@attr" that
              //       select the attribute because the fields could be
              //       relative to the selector element. -Ac
              //       Unless xpath starts with a descendant node -Achille Fokoue
              //      ... or a / or a . - NG
              super(((xpath.trim().startsWith("/") ||xpath.trim().startsWith("."))?
                      xpath:"./"+xpath),
                    symbolTable, context);
  
              // verify that only one attribute is selected per branch
              for (int i=0;i<fLocationPaths.length;i++) {
                  for(int j=0; j<fLocationPaths[i].steps.length; j++) {
                      Axis axis =
                          fLocationPaths[i].steps[j].axis;
                      if (axis.type == XPath.Axis.ATTRIBUTE &&
                              (j < fLocationPaths[i].steps.length-1)) {
                          throw new XPathException("c-fields-xpaths");
                      }
                  }
              }
          } // <init>(String,SymbolTable,NamespacesContext)
  
      } // class XPath
  
      /**
       * Field matcher.
       *
       * @author Andy Clark, IBM
       */
      protected class Matcher
          extends XPathMatcher {
  
          //
          // Data
          //
  
          /** Field activator. */
          protected FieldActivator fFieldActivator;
  
          /** Value store for data values. */
          protected ValueStore fStore;
  
          //
          // Constructors
          //
  
          /** Constructs a field matcher. */
          public Matcher(Field.XPath xpath, FieldActivator activator, ValueStore store) {
              super(xpath);
              fFieldActivator = activator;
              fStore = store;
          } // <init>(Field.XPath,ValueStore)
  
          //
          // XPathHandler methods
          //
  
          /**
           * This method is called when the XPath handler matches the
           * XPath expression.
           */
          protected void matched(Object actualValue, short valueType, ShortList itemValueType, boolean isNil) {
              super.matched(actualValue, valueType, itemValueType, isNil);
              if(isNil && (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY)) {
                  String code = "KeyMatchesNillable";
                  fStore.reportError(code,
                      new Object[]{fIdentityConstraint.getElementName(), fIdentityConstraint.getIdentityConstraintName()});
              }
              fStore.addValue(Field.this, actualValue, convertToPrimitiveKind(valueType), convertToPrimitiveKind(itemValueType));
              // once we've stored the value for this field, we set the mayMatch
              // member to false so that, in the same scope, we don't match any more
              // values (and throw an error instead).
              fFieldActivator.setMayMatch(Field.this, Boolean.FALSE);
          } // matched(String)
  
          private short convertToPrimitiveKind(short valueType) {
              /** Primitive datatypes. */
              if (valueType <= XSConstants.NOTATION_DT) {
                  return valueType;
              }
              /** Types derived from string. */
              if (valueType <= XSConstants.ENTITY_DT) {
                  return XSConstants.STRING_DT;
              }
              /** Types derived from decimal. */
              if (valueType <= XSConstants.POSITIVEINTEGER_DT) {
                  return XSConstants.DECIMAL_DT;
              }
              /** Other types. */
              return valueType;
          }
  
          private ShortList convertToPrimitiveKind(ShortList itemValueType) {
              if (itemValueType != null) {
                  int i;
                  final int length = itemValueType.getLength();
                  for (i = 0; i < length; ++i) {
                      short type = itemValueType.item(i);
                      if (type != convertToPrimitiveKind(type)) {
                          break;
                      }
                  }
                  if (i != length) {
                      final short [] arr = new short[length];
                      for (int j = 0; j < i; ++j) {
                          arr[j] = itemValueType.item(j);
                      }
                      for(; i < length; ++i) {
                          arr[i] = convertToPrimitiveKind(itemValueType.item(i));
                      }
                      return new ShortListImpl(arr, arr.length);
                  }
              }
              return itemValueType;
          }
  
          protected void handleContent(XSTypeDefinition type, boolean nillable, Object actualValue, short valueType, ShortList itemValueType) {
              if (type == null ||
                 type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE &&
                 ((XSComplexTypeDefinition) type).getContentType()
                  != XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
  
                      // the content must be simpleType content
                      fStore.reportError( "cvc-id.3", new Object[] {
                              fIdentityConstraint.getName(),
                              fIdentityConstraint.getElementName()});
  
              }
              fMatchedString = actualValue;
              matched(fMatchedString, valueType, itemValueType, nillable);
          } // handleContent(XSElementDecl, String)
  
      } // class Matcher
  
  } // class Field
  