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