1/* 2 * Copyright (c) 2006, 2009, Oracle and/or its affiliates. All rights reserved. 3 */ 4/* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. 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 21package com.sun.org.apache.xerces.internal.impl.xs.models; 22 23import com.sun.org.apache.xerces.internal.xni.QName; 24import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl; 25import com.sun.org.apache.xerces.internal.impl.xs.SubstitutionGroupHandler; 26import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaException; 27import com.sun.org.apache.xerces.internal.impl.xs.XSConstraints; 28import java.util.ArrayList; 29 30/** 31 * XSAllCM implements XSCMValidator and handles <all>. 32 * 33 * @xerces.internal 34 * 35 * @author Pavani Mukthipudi, Sun Microsystems Inc. 36 */ 37public class XSAllCM implements XSCMValidator { 38 39 // 40 // Constants 41 // 42 43 // start the content model: did not see any children 44 private static final short STATE_START = 0; 45 private static final short STATE_VALID = 1; 46 private static final short STATE_CHILD = 1; 47 48 49 // 50 // Data 51 // 52 53 private XSElementDecl fAllElements[]; 54 private boolean fIsOptionalElement[]; 55 private boolean fHasOptionalContent = false; 56 private int fNumElements = 0; 57 58 // 59 // Constructors 60 // 61 62 public XSAllCM (boolean hasOptionalContent, int size) { 63 fHasOptionalContent = hasOptionalContent; 64 fAllElements = new XSElementDecl[size]; 65 fIsOptionalElement = new boolean[size]; 66 } 67 68 public void addElement (XSElementDecl element, boolean isOptional) { 69 fAllElements[fNumElements] = element; 70 fIsOptionalElement[fNumElements] = isOptional; 71 fNumElements++; 72 } 73 74 75 // 76 // XSCMValidator methods 77 // 78 79 /** 80 * This methods to be called on entering a first element whose type 81 * has this content model. It will return the initial state of the 82 * content model 83 * 84 * @return Start state of the content model 85 */ 86 public int[] startContentModel() { 87 88 int[] state = new int[fNumElements + 1]; 89 90 for (int i = 0; i <= fNumElements; i++) { 91 state[i] = STATE_START; 92 } 93 return state; 94 } 95 96 // convinient method: when error occurs, to find a matching decl 97 // from the candidate elements. 98 Object findMatchingDecl(QName elementName, SubstitutionGroupHandler subGroupHandler) { 99 Object matchingDecl = null; 100 for (int i = 0; i < fNumElements; i++) { 101 matchingDecl = subGroupHandler.getMatchingElemDecl(elementName, fAllElements[i]); 102 if (matchingDecl != null) 103 break; 104 } 105 return matchingDecl; 106 } 107 108 /** 109 * The method corresponds to one transition in the content model. 110 * 111 * @param elementName 112 * @param currentState Current state 113 * @return an element decl object 114 */ 115 public Object oneTransition (QName elementName, int[] currentState, SubstitutionGroupHandler subGroupHandler) { 116 117 // error state 118 if (currentState[0] < 0) { 119 currentState[0] = XSCMValidator.SUBSEQUENT_ERROR; 120 return findMatchingDecl(elementName, subGroupHandler); 121 } 122 123 // seen child 124 currentState[0] = STATE_CHILD; 125 126 Object matchingDecl = null; 127 128 for (int i = 0; i < fNumElements; i++) { 129 // we only try to look for a matching decl if we have not seen 130 // this element yet. 131 if (currentState[i+1] != STATE_START) 132 continue; 133 matchingDecl = subGroupHandler.getMatchingElemDecl(elementName, fAllElements[i]); 134 if (matchingDecl != null) { 135 // found the decl, mark this element as "seen". 136 currentState[i+1] = STATE_VALID; 137 return matchingDecl; 138 } 139 } 140 141 // couldn't find the decl, change to error state. 142 currentState[0] = XSCMValidator.FIRST_ERROR; 143 return findMatchingDecl(elementName, subGroupHandler); 144 } 145 146 147 /** 148 * The method indicates the end of list of children 149 * 150 * @param currentState Current state of the content model 151 * @return true if the last state was a valid final state 152 */ 153 public boolean endContentModel (int[] currentState) { 154 155 int state = currentState[0]; 156 157 if (state == XSCMValidator.FIRST_ERROR || state == XSCMValidator.SUBSEQUENT_ERROR) { 158 return false; 159 } 160 161 // If <all> has minOccurs of zero and there are 162 // no children to validate, it is trivially valid 163 if (fHasOptionalContent && state == STATE_START) { 164 return true; 165 } 166 167 for (int i = 0; i < fNumElements; i++) { 168 // if one element is required, but not present, then error 169 if (!fIsOptionalElement[i] && currentState[i+1] == STATE_START) 170 return false; 171 } 172 173 return true; 174 } 175 176 /** 177 * check whether this content violates UPA constraint. 178 * 179 * @param subGroupHandler the substitution group handler 180 * @return true if this content model contains other or list wildcard 181 */ 182 public boolean checkUniqueParticleAttribution(SubstitutionGroupHandler subGroupHandler) throws XMLSchemaException { 183 // check whether there is conflict between any two leaves 184 for (int i = 0; i < fNumElements; i++) { 185 for (int j = i+1; j < fNumElements; j++) { 186 if (XSConstraints.overlapUPA(fAllElements[i], fAllElements[j], subGroupHandler)) { 187 // REVISIT: do we want to report all errors? or just one? 188 throw new XMLSchemaException("cos-nonambig", new Object[]{fAllElements[i].toString(), 189 fAllElements[j].toString()}); 190 } 191 } 192 } 193 194 return false; 195 } 196 197 /** 198 * Check which elements are valid to appear at this point. This method also 199 * works if the state is in error, in which case it returns what should 200 * have been seen. 201 * 202 * @param state the current state 203 * @return a list whose entries are instances of 204 * either XSWildcardDecl or XSElementDecl. 205 */ 206 public ArrayList whatCanGoHere(int[] state) { 207 ArrayList ret = new ArrayList(); 208 for (int i = 0; i < fNumElements; i++) { 209 // we only try to look for a matching decl if we have not seen 210 // this element yet. 211 if (state[i+1] == STATE_START) { 212 ret.add(fAllElements[i]); 213 } 214 } 215 return ret; 216 } 217 218 public ArrayList checkMinMaxBounds() { 219 return null; 220 } 221 222 public int [] occurenceInfo(int[] state) { 223 return null; 224 } 225 226 public String getTermName(int termId) { 227 return null; 228 } 229 230 public boolean isCompactedForUPA() { 231 return false; 232 } 233} // class XSAllCM 234