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