~ubuntu-branches/ubuntu/wily/opencollada/wily-proposed

« back to all changes in this revision

Viewing changes to xsd2cppsax/src/de/netallied/xsd2cppsax/statemachine/StateMachineBuilder.java

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2015-05-14 17:23:27 UTC
  • Revision ID: package-import@ubuntu.com-20150514172327-f862u8envms01fra
Tags: upstream-0.1.0~20140703.ddf8f47+dfsg1
ImportĀ upstreamĀ versionĀ 0.1.0~20140703.ddf8f47+dfsg1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 *   Copyright © 2008-2012 NetAllied Systems GmbH, Ravensburg, Germany. 
 
3
 *       
 
4
 *   Licensed under the MIT Open Source License, 
 
5
 *   for details please see LICENSE file or the website
 
6
 *   http://www.opensource.org/licenses/mit-license.php
 
7
*/
 
8
package de.netallied.xsd2cppsax.statemachine;
 
9
 
 
10
import java.util.ArrayList;
 
11
import java.util.List;
 
12
 
 
13
import org.apache.xerces.xs.XSComplexTypeDefinition;
 
14
import org.apache.xerces.xs.XSElementDeclaration;
 
15
import org.apache.xerces.xs.XSModelGroup;
 
16
import org.apache.xerces.xs.XSParticle;
 
17
import org.apache.xerces.xs.XSTypeDefinition;
 
18
 
 
19
import de.netallied.xsd2cppsax.Constants;
 
20
 
 
21
/**
 
22
 * Builds a state machine from a XSD complex type.
 
23
 * 
 
24
 */
 
25
public class StateMachineBuilder {
 
26
 
 
27
    /**
 
28
     * Small helper class to handle model groups with maxOccurs=unbounded.
 
29
     * <p>
 
30
     * e.g.
 
31
     * 
 
32
     * <pre>
 
33
     * &lt;sequence&gt;
 
34
     *      &lt;dog&gt;
 
35
     *      &lt;choice minOccurs=&quot;0&quot; maxOccurs=&quot;unbounded&quot;&gt;
 
36
     *          &lt;cat&gt;
 
37
     *          &lt;sequence&gt;
 
38
     *              &lt;black&gt;
 
39
     *              &lt;white&gt;
 
40
     *          &lt;/sequence&gt;
 
41
     *      &lt;/choice&gt;
 
42
     *      &lt;mouse&gt;
 
43
     * &lt;/sequence&gt;
 
44
     * </pre>
 
45
     * 
 
46
     * We need links from
 
47
     * <ul>
 
48
     * <li>cat to cat</li>
 
49
     * <li>cat to black</li>
 
50
     * <li>white to cat</li>
 
51
     * <li>white to black</li>
 
52
     * </ul>
 
53
     * This class' purpose is to return black and white from the above example.
 
54
     * black would be included in {@link #beginStates} and white in
 
55
     * {@link #endStates}.
 
56
     * </p>
 
57
     * 
 
58
         */
 
59
    protected static class ListPair {
 
60
        protected List<StateMachineNode> beginStates;
 
61
 
 
62
        protected List<StateMachineNode> endStates;
 
63
 
 
64
        protected ListPair() {
 
65
            beginStates = new ArrayList<StateMachineNode>();
 
66
            endStates = new ArrayList<StateMachineNode>();
 
67
        }
 
68
    }
 
69
 
 
70
    /**
 
71
     * Starts building of a state machine.
 
72
     * 
 
73
     * @param type
 
74
     *            XSD type to build state machine for.
 
75
     * @return State machine or null.
 
76
     */
 
77
    public StateMachineRootNode build(XSComplexTypeDefinition type) {
 
78
        if (type != null && type.getParticle() != null) {
 
79
            return build(type.getParticle());
 
80
        } else if (type != null && type.getBaseType() != null) {
 
81
            return build(type.getBaseType());
 
82
        }
 
83
        return null;
 
84
    }
 
85
 
 
86
    /**
 
87
     * Does real state machine building. To be called after types have been
 
88
     * checked and may be called for base types.
 
89
     * 
 
90
     * @param particle
 
91
     *            XSParticle to build state machine for.
 
92
     * @return State machine or null.
 
93
     */
 
94
    protected StateMachineRootNode build(XSParticle particle) {
 
95
        if (particle.getTerm() instanceof XSModelGroup) {
 
96
            XSModelGroup modelGroup = (XSModelGroup) particle.getTerm();
 
97
            boolean foundNestedModelGroup = false;
 
98
            for (int i = 0; i < modelGroup.getParticles().getLength(); i++) {
 
99
                XSParticle subParticle = (XSParticle) modelGroup.getParticles().item(i);
 
100
                if (subParticle.getTerm() instanceof XSModelGroup) {
 
101
                    foundNestedModelGroup = true;
 
102
                    break;
 
103
                }
 
104
            }
 
105
            if (!foundNestedModelGroup) {
 
106
                return null;
 
107
            }
 
108
 
 
109
            StateMachineRootNode rootNode = new StateMachineRootNode(Constants.STATE_MACHINE_ROOT_NODE_NAME);
 
110
            List<StateMachineNode> tmpList = new ArrayList<StateMachineNode>();
 
111
            tmpList.add(rootNode);
 
112
            tmpList = handleModelGroup(modelGroup, tmpList, rootNode, particle).endStates;
 
113
            StateMachineNode endNode = new StateMachineNode(Constants.STATE_MACHINE_END_NODE_NAME);
 
114
            rootNode.registerNode(endNode.getName(), endNode);
 
115
            for (StateMachineNode node : tmpList) {
 
116
                node.addFollowing(endNode);
 
117
            }
 
118
            return rootNode;
 
119
        }
 
120
        return null;
 
121
    }
 
122
 
 
123
    /**
 
124
     * Convenience method allowing to pass any types.
 
125
     */
 
126
    public StateMachineRootNode build(XSTypeDefinition type) {
 
127
        if (type instanceof XSComplexTypeDefinition) {
 
128
            return build((XSComplexTypeDefinition) type);
 
129
        }
 
130
        return null;
 
131
    }
 
132
 
 
133
    /**
 
134
     * Recursive function to add elements of model group to existing state
 
135
     * machine.
 
136
     * 
 
137
     * @param modelGroup
 
138
     *            Model group to handle.
 
139
     * @param previousNodes
 
140
     *            Existing state machine.
 
141
     * @param rootNode
 
142
     *            Root node of current state machine. Used to register nodes.
 
143
     * @param modelGroupParticle
 
144
     *            Particle of given model group. Needed for min/maxOccurs of
 
145
     *            whole model group.
 
146
     * @return Nodes which need following states.
 
147
     */
 
148
    protected ListPair handleModelGroup(XSModelGroup modelGroup, List<StateMachineNode> previousNodes,
 
149
            StateMachineRootNode rootNode, XSParticle modelGroupParticle) {
 
150
 
 
151
        if (modelGroupParticle.getTerm() != modelGroup) {
 
152
            throw new IllegalArgumentException("given model group and particle don't match.");
 
153
        }
 
154
 
 
155
        ListPair returnLists = new ListPair();
 
156
        List<StateMachineNode> originalPreviousNodes = new ArrayList<StateMachineNode>();
 
157
        originalPreviousNodes.addAll(previousNodes);
 
158
 
 
159
        switch (modelGroup.getCompositor()) {
 
160
 
 
161
        case XSModelGroup.COMPOSITOR_SEQUENCE:
 
162
            for (int i = 0; i < modelGroup.getParticles().getLength(); i++) {
 
163
                XSParticle particle = (XSParticle) modelGroup.getParticles().item(i);
 
164
 
 
165
                if (particle.getTerm() instanceof XSElementDeclaration) {
 
166
                    StateMachineNode newNode = new StateMachineNode(particle.getTerm().getName());
 
167
                    rootNode.registerNode(newNode.getName(), newNode);
 
168
 
 
169
                    if (particle.getMaxOccursUnbounded()) {
 
170
                        newNode.addFollowing(newNode);
 
171
                    }
 
172
 
 
173
                    List<StateMachineNode> tmp = new ArrayList<StateMachineNode>();
 
174
                    for (StateMachineNode prevNode : previousNodes) {
 
175
                        prevNode.addFollowing(newNode);
 
176
 
 
177
                        if (particle.getMinOccurs() == 0) {
 
178
                            tmp.add(prevNode);
 
179
                        }
 
180
                    }
 
181
                    previousNodes = tmp;
 
182
                    previousNodes.add(newNode);
 
183
 
 
184
                    if (i == 0) {
 
185
                        returnLists.beginStates.add(newNode);
 
186
                    }
 
187
 
 
188
                } else if (particle.getTerm() instanceof XSModelGroup) {
 
189
                    ListPair listPair = handleModelGroup((XSModelGroup) particle.getTerm(), previousNodes, rootNode,
 
190
                            particle);
 
191
                    previousNodes = listPair.endStates;
 
192
 
 
193
                    if (i == 0) {
 
194
                        returnLists.beginStates.addAll(listPair.beginStates);
 
195
                    }
 
196
                }
 
197
 
 
198
            }
 
199
            returnLists.endStates = previousNodes;
 
200
            break;
 
201
 
 
202
        case XSModelGroup.COMPOSITOR_CHOICE:
 
203
            for (int i = 0; i < modelGroup.getParticles().getLength(); i++) {
 
204
                XSParticle particle = (XSParticle) modelGroup.getParticles().item(i);
 
205
 
 
206
                if (particle.getTerm() instanceof XSElementDeclaration) {
 
207
                    StateMachineNode newNode = new StateMachineNode(particle.getTerm().getName());
 
208
                    rootNode.registerNode(newNode.getName(), newNode);
 
209
                    returnLists.endStates.add(newNode);
 
210
                    returnLists.beginStates.add(newNode);
 
211
 
 
212
                    if (particle.getMinOccurs() == 0) {
 
213
                        for (StateMachineNode prevNode : previousNodes) {
 
214
                            if (!returnLists.endStates.contains(prevNode)) {
 
215
                                returnLists.endStates.add(prevNode);
 
216
                            }
 
217
                        }
 
218
                    }
 
219
                    if (particle.getMaxOccursUnbounded()) {
 
220
                        newNode.addFollowing(newNode);
 
221
                    }
 
222
 
 
223
                    for (StateMachineNode prevNode : previousNodes) {
 
224
                        prevNode.addFollowing(newNode);
 
225
                    }
 
226
 
 
227
                } else if (particle.getTerm() instanceof XSModelGroup) {
 
228
                    ListPair listPair = handleModelGroup((XSModelGroup) particle.getTerm(), previousNodes, rootNode,
 
229
                            particle);
 
230
                    returnLists.endStates.addAll(listPair.endStates);
 
231
                    returnLists.beginStates.addAll(listPair.beginStates);
 
232
                }
 
233
            }
 
234
 
 
235
            break;
 
236
 
 
237
        }
 
238
 
 
239
        if (modelGroupParticle.getMaxOccursUnbounded()) {
 
240
            for (StateMachineNode endNode : returnLists.endStates) {
 
241
                for (StateMachineNode beginNode : returnLists.beginStates) {
 
242
                    endNode.addFollowing(beginNode);
 
243
                }
 
244
            }
 
245
        }
 
246
        if (modelGroupParticle.getMinOccurs() == 0) {
 
247
            for (StateMachineNode prevNode : originalPreviousNodes) {
 
248
                if (!returnLists.endStates.contains(prevNode)) {
 
249
                    returnLists.endStates.add(prevNode);
 
250
                }
 
251
            }
 
252
        }
 
253
 
 
254
        return returnLists;
 
255
    }
 
256
}