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.dtd.models; 23 24import com.sun.org.apache.xerces.internal.xni.QName; 25 26import com.sun.org.apache.xerces.internal.impl.dtd.XMLContentSpec; 27 28/** 29 * SimpleContentModel is a derivative of the abstract content model base 30 * class that handles a small set of simple content models that are just 31 * way overkill to give the DFA treatment. 32 * <p> 33 * This class handles the following scenarios: 34 * <ul> 35 * <li> a 36 * <li> a? 37 * <li> a* 38 * <li> a+ 39 * <li> a,b 40 * <li> a|b 41 * </ul> 42 * <p> 43 * These all involve a unary operation with one element type, or a binary 44 * operation with two elements. These are very simple and can be checked 45 * in a simple way without a DFA and without the overhead of setting up a 46 * DFA for such a simple check. 47 * 48 * @xerces.internal 49 * 50 */ 51public class SimpleContentModel 52 implements ContentModelValidator { 53 54 // 55 // Constants 56 // 57 58 /** CHOICE */ 59 public static final short CHOICE = -1; 60 61 /** SEQUENCE */ 62 public static final short SEQUENCE = -1; 63 64 // 65 // Data 66 // 67 68 69 /** 70 * The element decl pool indices of the first (and optional second) 71 * child node. The operation code tells us whether the second child 72 * is used or not. 73 */ 74 private QName fFirstChild = new QName(); 75 76 /** 77 * The element decl pool indices of the first (and optional second) 78 * child node. The operation code tells us whether the second child 79 * is used or not. 80 */ 81 private QName fSecondChild = new QName(); 82 83 /** 84 * The operation that this object represents. Since this class only 85 * does simple contents, there is only ever a single operation 86 * involved (i.e. the children of the operation are always one or 87 * two leafs.) This is one of the XMLDTDParams.CONTENTSPECNODE_XXX values. 88 */ 89 private int fOperator; 90 91 /* this is the EquivClassComparator object */ 92 //private EquivClassComparator comparator = null; 93 94 95 // 96 // Constructors 97 // 98 99 /** 100 * Constructs a simple content model. 101 * 102 * @param operator The content model operator. 103 * @param firstChild qualified name of the first child 104 * @param secondChild qualified name of the second child 105 * 106 */ 107 public SimpleContentModel(short operator, QName firstChild, QName secondChild) { 108 // 109 // Store away the children and operation. This is all we need to 110 // do the content model check. 111 // 112 // The operation is one of the ContentSpecNode.NODE_XXX values! 113 // 114 fFirstChild.setValues(firstChild); 115 if (secondChild != null) { 116 fSecondChild.setValues(secondChild); 117 } 118 else { 119 fSecondChild.clear(); 120 } 121 fOperator = operator; 122 } 123 124 // 125 // ContentModelValidator methods 126 // 127 128 /** 129 * Check that the specified content is valid according to this 130 * content model. This method can also be called to do 'what if' 131 * testing of content models just to see if they would be valid. 132 * <p> 133 * A value of -1 in the children array indicates a PCDATA node. All other 134 * indexes will be positive and represent child elements. The count can be 135 * zero, since some elements have the EMPTY content model and that must be 136 * confirmed. 137 * 138 * @param children The children of this element. Each integer is an index within 139 * the <code>StringPool</code> of the child element name. An index 140 * of -1 is used to indicate an occurrence of non-whitespace character 141 * data. 142 * @param offset Offset into the array where the children starts. 143 * @param length The number of entries in the <code>children</code> array. 144 * 145 * @return The value -1 if fully valid, else the 0 based index of the child 146 * that first failed. If the value returned is equal to the number 147 * of children, then the specified children are valid but additional 148 * content is required to reach a valid ending state. 149 * 150 */ 151 public int validate(QName[] children, int offset, int length) { 152 153 // 154 // According to the type of operation, we do the correct type of 155 // content check. 156 // 157 switch(fOperator) 158 { 159 case XMLContentSpec.CONTENTSPECNODE_LEAF : 160 // If there is not a child, then report an error at index 0 161 if (length == 0) 162 return 0; 163 164 // If the 0th child is not the right kind, report an error at 0 165 if (children[offset].rawname != fFirstChild.rawname) { 166 return 0; 167 } 168 169 // If more than one child, report an error at index 1 170 if (length > 1) 171 return 1; 172 break; 173 174 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE : 175 // 176 // If there is one child, make sure its the right type. If not, 177 // then its an error at index 0. 178 // 179 if (length == 1) { 180 if (children[offset].rawname != fFirstChild.rawname) { 181 return 0; 182 } 183 } 184 185 // 186 // If the child count is greater than one, then obviously 187 // bad, so report an error at index 1. 188 // 189 if (length > 1) 190 return 1; 191 break; 192 193 case XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE : 194 // 195 // If the child count is zero, that's fine. If its more than 196 // zero, then make sure that all children are of the element 197 // type that we stored. If not, report the index of the first 198 // failed one. 199 // 200 if (length > 0) 201 { 202 for (int index = 0; index < length; index++) { 203 if (children[offset + index].rawname != fFirstChild.rawname) { 204 return index; 205 } 206 } 207 } 208 break; 209 210 case XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE : 211 // 212 // If the child count is zero, that's an error so report 213 // an error at index 0. 214 // 215 if (length == 0) 216 return 0; 217 218 // 219 // Otherwise we have to check them all to make sure that they 220 // are of the correct child type. If not, then report the index 221 // of the first one that is not. 222 // 223 for (int index = 0; index < length; index++) { 224 if (children[offset + index].rawname != fFirstChild.rawname) { 225 return index; 226 } 227 } 228 break; 229 230 case XMLContentSpec.CONTENTSPECNODE_CHOICE : 231 // 232 // There must be one and only one child, so if the element count 233 // is zero, return an error at index 0. 234 // 235 if (length == 0) 236 return 0; 237 238 // If the zeroth element isn't one of our choices, error at 0 239 if ((children[offset].rawname != fFirstChild.rawname) && 240 (children[offset].rawname != fSecondChild.rawname)) { 241 return 0; 242 } 243 244 // If there is more than one element, then an error at 1 245 if (length > 1) 246 return 1; 247 break; 248 249 case XMLContentSpec.CONTENTSPECNODE_SEQ : 250 // 251 // There must be two children and they must be the two values 252 // we stored, in the stored order. 253 // 254 if (length == 2) { 255 if (children[offset].rawname != fFirstChild.rawname) { 256 return 0; 257 } 258 if (children[offset + 1].rawname != fSecondChild.rawname) { 259 return 1; 260 } 261 } 262 else { 263 if (length > 2) { 264 return 2; 265 } 266 267 return length; 268 } 269 270 break; 271 272 default : 273 throw new RuntimeException("ImplementationMessages.VAL_CST"); 274 } 275 276 // We survived, so return success status 277 return -1; 278 } // validate 279 280} // class SimpleContentModel 281