001/**
002The contents of this file are subject to the Mozilla Public License Version 1.1 
003(the "License"); you may not use this file except in compliance with the License. 
004You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
005Software distributed under the License is distributed on an "AS IS" basis, 
006WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
007specific language governing rights and limitations under the License. 
008
009The Original Code is "StructureDefinition.java".  Description: 
010"A definition element" 
011
012The Initial Developer of the Original Code is University Health Network. Copyright (C) 
0132001.  All Rights Reserved. 
014
015Contributor(s): ______________________________________. 
016
017Alternatively, the contents of this file may be used under the terms of the 
018GNU General Public License (the  �GPL�), in which case the provisions of the GPL are 
019applicable instead of those above.  If you wish to allow use of your version of this 
020file only under the terms of the GPL and not to allow others to use your version 
021of this file under the MPL, indicate your decision by deleting  the provisions above 
022and replace  them with the notice and other provisions required by the GPL License.  
023If you do not delete the provisions above, a recipient may use your version of 
024this file under either the MPL or the GPL. 
025
026 */
027package ca.uhn.hl7v2.parser;
028
029import java.util.ArrayList;
030import java.util.HashSet;
031import java.util.Set;
032
033/**
034 * Defines
035 * 
036 * @author James
037 * 
038 */
039public class StructureDefinition implements IStructureDefinition {
040
041    private HashSet<String> myAllChildrenNames;
042    private HashSet<String> myAllFirstLeafNames;
043    private ArrayList<StructureDefinition> myChildren = new ArrayList<StructureDefinition>();
044    private IStructureDefinition myFirstSibling;
045    private boolean myFirstSiblingIsSet;
046    private Boolean myIsFinalChildOfParent;
047    private boolean myIsRepeating;
048    private boolean myIsRequired;
049    private boolean myIsSegment;
050    private String myName;
051    private String myNameAsItAppearsInParent;
052    private Set<String> myNamesOfAllPossibleFollowingLeaves;
053    private IStructureDefinition myNextLeaf;
054    private IStructureDefinition myNextSibling;
055    private IStructureDefinition myParent;
056    private int myPosition;
057
058
059    /**
060     * Constructor
061     */
062    public StructureDefinition() {
063    }
064
065
066    /**
067     * Setter
068     */
069    void addChild(StructureDefinition theChild) {
070        myChildren.add(theChild);
071    }
072
073
074    /**
075     * {@inheritDoc }
076     */
077    @Override
078    public boolean equals(Object theObj) {
079        if (theObj == null || !(theObj instanceof StructureDefinition)) {
080            return false;
081        }
082        StructureDefinition o = (StructureDefinition) theObj;
083        return o.myName.equals(myName) && o.myPosition == myPosition;
084    }
085
086
087    /**
088     * {@inheritDoc }
089     */
090    public HashSet<String> getAllChildNames() {
091        if (myAllChildrenNames == null) {
092            myAllChildrenNames = new HashSet<String>();
093            for (IStructureDefinition next : myChildren) {
094                myAllChildrenNames.add(next.getName());
095                myAllChildrenNames.addAll(next.getAllChildNames());
096            }
097        }
098
099        return myAllChildrenNames;
100    }
101
102
103    /**
104     * {@inheritDoc }
105     */
106    public HashSet<String> getAllPossibleFirstChildren() {
107        if (myAllFirstLeafNames == null) {
108            myAllFirstLeafNames = new HashSet<String>();
109            for (IStructureDefinition next : myChildren) {
110                myAllFirstLeafNames.addAll(next.getAllPossibleFirstChildren());
111                if (next.isRequired()) {
112                    break;
113                }
114            }
115
116            myAllFirstLeafNames.add(getName());
117        }
118
119        return myAllFirstLeafNames;
120    }
121
122
123    /**
124     * {@inheritDoc }
125     */
126    public ArrayList<StructureDefinition> getChildren() {
127        return myChildren;
128    }
129
130
131    /**
132     * {@inheritDoc }
133     */
134    public IStructureDefinition getFirstChild() {
135        return myChildren.get(0);
136    }
137
138
139    /**
140     * {@inheritDoc }
141     */
142    public IStructureDefinition getFirstSibling() {
143        if (!myFirstSiblingIsSet) {
144            if (myParent == null) {
145                myFirstSibling = null;
146            } else if (myParent.getChildren().get(0) == this) {
147                myFirstSibling = null;
148            } else {
149                myFirstSibling = myParent.getChildren().get(0);
150            }
151            myFirstSiblingIsSet = true;
152        }
153
154        return myFirstSibling;
155    }
156
157
158    /**
159     * {@inheritDoc }
160     */
161    public String getName() {
162        return myName;
163    }
164
165
166    /**
167     * {@inheritDoc}
168     */
169    public String getNameAsItAppearsInParent() {
170        return myNameAsItAppearsInParent;
171    }
172
173
174    /**
175     * {@inheritDoc }
176     */
177    public Set<String> getNamesOfAllPossibleFollowingLeaves() {
178        if (myNamesOfAllPossibleFollowingLeaves != null) {
179            return myNamesOfAllPossibleFollowingLeaves;
180        }
181
182        myNamesOfAllPossibleFollowingLeaves = new HashSet<String>();
183
184        IStructureDefinition nextLeaf = getNextLeaf();
185        if (nextLeaf != null) {
186            myNamesOfAllPossibleFollowingLeaves.add(nextLeaf.getName());
187            myNamesOfAllPossibleFollowingLeaves.addAll(nextLeaf.getNamesOfAllPossibleFollowingLeaves());
188        }
189
190        IStructureDefinition parent = myParent;
191        while (parent != null) {
192            if (parent.isRepeating()) {
193                myNamesOfAllPossibleFollowingLeaves.addAll(parent.getAllPossibleFirstChildren());
194            }
195            parent = parent.getParent();
196        }
197
198        return myNamesOfAllPossibleFollowingLeaves;
199
200    }
201
202
203    /**
204     * {@inheritDoc }
205     */
206    public IStructureDefinition getNextLeaf() {
207        return myNextLeaf;
208    }
209
210
211    /**
212     * {@inheritDoc }
213     */
214    public IStructureDefinition getNextSibling() {
215        if (myNextSibling != null) {
216            return myNextSibling;
217        }
218
219        if (isFinalChildOfParent()) {
220            throw new IllegalStateException("Final child");
221        }
222
223        myNextSibling = myParent.getChildren().get(myPosition + 1);
224        return myNextSibling;
225    }
226
227
228    /**
229     * {@inheritDoc }
230     */
231    public IStructureDefinition getParent() {
232        return myParent;
233    }
234
235
236    /**
237     * {@inheritDoc }
238     */
239    public int getPosition() {
240        return myPosition;
241    }
242
243
244    /**
245     * {@inheritDoc }
246     */
247    public boolean hasChildren() {
248        return myChildren.isEmpty() == false;
249    }
250
251
252    /**
253     * {@inheritDoc }
254     */
255    @Override
256    public int hashCode() {
257        return 17 * myName.hashCode() * myPosition;
258    }
259
260
261    /**
262     * {@inheritDoc }
263     */
264    public boolean isFinalChildOfParent() {
265        if (myIsFinalChildOfParent != null) {
266            return myIsFinalChildOfParent;
267        }
268
269        if (myParent == null) {
270            myIsFinalChildOfParent = true;
271        } else {
272            myIsFinalChildOfParent = (myPosition == (myParent.getChildren().size() - 1));
273        }
274
275        return myIsFinalChildOfParent;
276    }
277
278
279    /**
280     * {@inheritDoc }
281     */
282    public boolean isRepeating() {
283        return myIsRepeating;
284    }
285
286
287    /**
288     * {@inheritDoc }
289     */
290    public boolean isRequired() {
291        return myIsRequired;
292    }
293
294
295    /**
296     * {@inheritDoc }
297     */
298    public boolean isSegment() {
299        return myIsSegment;
300    }
301
302
303    /**
304     * Setter
305     */
306    void setName(String theName) {
307        myName = theName;
308    }
309
310
311    /**
312     * Setter
313     */
314    void setNameAsItAppearsInParent(String theName) {
315        myNameAsItAppearsInParent = theName;
316    }
317
318
319    /**
320     * Setter
321     */
322    void setNextLeaf(IStructureDefinition theNextLeaf) {
323        myNextLeaf = theNextLeaf;
324    }
325
326
327    /**
328     * Setter
329     */
330    void setParent(IStructureDefinition theParent) {
331        myParent = theParent;
332    }
333
334
335    /**
336     * Setter
337     */
338    void setPosition(int thePosition) {
339        myPosition = thePosition;
340    }
341
342
343    /**
344     * Setter
345     */
346    void setRepeating(boolean theIsRepeating) {
347        myIsRepeating = theIsRepeating;
348    }
349
350
351    /**
352     * Setter
353     */
354    void setRequired(boolean theIsRequired) {
355        myIsRequired = theIsRequired;
356    }
357
358
359    /**
360     * Setter
361     */
362    void setSegment(boolean theIsSegment) {
363        myIsSegment = theIsSegment;
364    }
365
366
367    /**
368     * {@inheritDoc }
369     */
370    @Override
371    public String toString() {
372        return "StructureDefinition[" + getName() + "]";
373    }
374
375}