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        private boolean myChoiceElement;
058
059
060    /**
061     * Constructor
062     */
063    public StructureDefinition() {
064    }
065
066
067    /**
068     * Setter
069     */
070    void addChild(StructureDefinition theChild) {
071        myChildren.add(theChild);
072    }
073
074
075    /**
076     * {@inheritDoc }
077     */
078    @Override
079    public boolean equals(Object theObj) {
080        if (theObj == null || !(theObj instanceof StructureDefinition)) {
081            return false;
082        }
083        StructureDefinition o = (StructureDefinition) theObj;
084        return o.myName.equals(myName) && o.myPosition == myPosition;
085    }
086
087
088    /**
089     * {@inheritDoc }
090     */
091    public HashSet<String> getAllChildNames() {
092        if (myAllChildrenNames == null) {
093            myAllChildrenNames = new HashSet<String>();
094            for (IStructureDefinition next : myChildren) {
095                myAllChildrenNames.add(next.getName());
096                myAllChildrenNames.addAll(next.getAllChildNames());
097            }
098        }
099
100        return myAllChildrenNames;
101    }
102
103
104    /**
105     * {@inheritDoc }
106     */
107    public HashSet<String> getAllPossibleFirstChildren() {
108        if (myAllFirstLeafNames == null) {
109            myAllFirstLeafNames = new HashSet<String>();
110            
111            boolean hasChoice = false;
112            for (IStructureDefinition next : myChildren) {
113                myAllFirstLeafNames.addAll(next.getAllPossibleFirstChildren());
114                
115                if (next.isChoiceElement()) {
116                        hasChoice = true;
117                        continue;
118                } else if (hasChoice) {
119                        break;
120                }
121                
122                if (next.isRequired()) {
123                    break;
124                }
125            }
126
127            myAllFirstLeafNames.add(getName());
128        }
129
130        return myAllFirstLeafNames;
131    }
132
133
134    /**
135     * {@inheritDoc }
136     */
137    public ArrayList<StructureDefinition> getChildren() {
138        return myChildren;
139    }
140
141
142    /**
143     * {@inheritDoc }
144     */
145    public IStructureDefinition getFirstChild() {
146        return myChildren.get(0);
147    }
148
149
150    /**
151     * {@inheritDoc }
152     */
153    public IStructureDefinition getFirstSibling() {
154        if (!myFirstSiblingIsSet) {
155            if (myParent == null) {
156                myFirstSibling = null;
157            } else if (myParent.getChildren().get(0) == this) {
158                myFirstSibling = null;
159            } else {
160                myFirstSibling = myParent.getChildren().get(0);
161            }
162            myFirstSiblingIsSet = true;
163        }
164
165        return myFirstSibling;
166    }
167
168
169    /**
170     * {@inheritDoc }
171     */
172    public String getName() {
173        return myName;
174    }
175
176
177    /**
178     * {@inheritDoc}
179     */
180    public String getNameAsItAppearsInParent() {
181        return myNameAsItAppearsInParent;
182    }
183
184
185    /**
186     * {@inheritDoc }
187     */
188    public Set<String> getNamesOfAllPossibleFollowingLeaves() {
189        if (myNamesOfAllPossibleFollowingLeaves != null) {
190            return myNamesOfAllPossibleFollowingLeaves;
191        }
192
193        myNamesOfAllPossibleFollowingLeaves = new HashSet<String>();
194
195        IStructureDefinition nextLeaf = getNextLeaf();
196        if (nextLeaf != null) {
197            myNamesOfAllPossibleFollowingLeaves.add(nextLeaf.getName());
198            myNamesOfAllPossibleFollowingLeaves.addAll(nextLeaf.getNamesOfAllPossibleFollowingLeaves());
199        }
200
201        IStructureDefinition parent = myParent;
202        while (parent != null) {
203            if (parent.isRepeating()) {
204                myNamesOfAllPossibleFollowingLeaves.addAll(parent.getAllPossibleFirstChildren());
205            }
206            parent = parent.getParent();
207        }
208
209        return myNamesOfAllPossibleFollowingLeaves;
210
211    }
212
213
214    /**
215     * {@inheritDoc }
216     */
217    public IStructureDefinition getNextLeaf() {
218        return myNextLeaf;
219    }
220
221
222    /**
223     * {@inheritDoc }
224     */
225    public IStructureDefinition getNextSibling() {
226        if (myNextSibling != null) {
227            return myNextSibling;
228        }
229
230        if (isFinalChildOfParent()) {
231            throw new IllegalStateException("Final child");
232        }
233
234        myNextSibling = myParent.getChildren().get(myPosition + 1);
235        return myNextSibling;
236    }
237
238
239    /**
240     * {@inheritDoc }
241     */
242    public IStructureDefinition getParent() {
243        return myParent;
244    }
245
246
247    /**
248     * {@inheritDoc }
249     */
250    public int getPosition() {
251        return myPosition;
252    }
253
254
255    /**
256     * {@inheritDoc }
257     */
258    public boolean hasChildren() {
259        return !myChildren.isEmpty();
260    }
261
262
263    /**
264     * {@inheritDoc }
265     */
266    @Override
267    public int hashCode() {
268        return 17 * myName.hashCode() * myPosition;
269    }
270
271
272    /**
273     * {@inheritDoc }
274     */
275    public boolean isFinalChildOfParent() {
276        if (myIsFinalChildOfParent != null) {
277            return myIsFinalChildOfParent;
278        }
279        myIsFinalChildOfParent = myParent == null || (myPosition == (myParent.getChildren().size() - 1));
280        return myIsFinalChildOfParent;
281    }
282
283
284    /**
285     * {@inheritDoc }
286     */
287    public boolean isRepeating() {
288        return myIsRepeating;
289    }
290
291
292    /**
293     * {@inheritDoc }
294     */
295    public boolean isRequired() {
296        return myIsRequired;
297    }
298
299
300    /**
301     * {@inheritDoc }
302     */
303    public boolean isSegment() {
304        return myIsSegment;
305    }
306
307
308    /**
309     * Setter
310     */
311    void setName(String theName) {
312        myName = theName;
313    }
314
315
316    /**
317     * Setter
318     */
319    void setNameAsItAppearsInParent(String theName) {
320        myNameAsItAppearsInParent = theName;
321    }
322
323
324    /**
325     * Setter
326     */
327    void setNextLeaf(IStructureDefinition theNextLeaf) {
328        myNextLeaf = theNextLeaf;
329    }
330
331
332    /**
333     * Setter
334     */
335    void setParent(IStructureDefinition theParent) {
336        myParent = theParent;
337    }
338
339
340    /**
341     * Setter
342     */
343    void setPosition(int thePosition) {
344        myPosition = thePosition;
345    }
346
347
348    /**
349     * Setter
350     */
351    void setRepeating(boolean theIsRepeating) {
352        myIsRepeating = theIsRepeating;
353    }
354
355
356    /**
357     * Setter
358     */
359    void setRequired(boolean theIsRequired) {
360        myIsRequired = theIsRequired;
361    }
362
363
364    /**
365     * Setter
366     */
367    void setSegment(boolean theIsSegment) {
368        myIsSegment = theIsSegment;
369    }
370
371
372    /**
373     * {@inheritDoc }
374     */
375    @Override
376    public String toString() {
377        return "StructureDefinition[" + getName() + "]";
378    }
379
380
381        /**
382     * @param theChoiceElement true if the definition of this structure is a choice
383         * @see ca.uhn.hl7v2.model.Group#isChoiceElement(String)
384     */
385        public void setChoiceElement(boolean theChoiceElement) {
386                myChoiceElement = theChoiceElement;
387        }
388
389
390        /**
391         * @see ca.uhn.hl7v2.model.Group#isChoiceElement(String)
392         */
393        public boolean isChoiceElement() {
394                return myChoiceElement;
395        }
396
397}