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 "Location.java".  Description: 
010"Location of an validated message element" 
011
012The Initial Developer of the Original Code is University Health Network. Copyright (C) 
0132012.  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 */
026package ca.uhn.hl7v2;
027
028import java.util.Collection;
029import java.util.Collections;
030import java.util.Stack;
031
032/**
033 * Location class to determine the location of an element
034 * 
035 * @author Christian Ohr
036 */
037public class Location {
038
039    private Stack<GroupLocation> groups = new Stack<>();
040        private String segmentName = null;
041        private int segmentRepetition = 0;
042        private int field = -1;
043        private int fieldRepetition = 0;
044        private int component = -1;
045        private int subcomponent = -1;
046
047    private boolean componentLevel;
048
049        public static final Location UNKNOWN = new Location();
050
051        public Location() {
052        }
053
054        public Location(Location l) {
055        this.groups = new Stack<>();
056        groups.addAll(l.groups);
057                this.segmentName = l.segmentName;
058                this.segmentRepetition = l.segmentRepetition;
059                this.field = l.field;
060                this.fieldRepetition = l.fieldRepetition;
061                this.component = l.component;
062                this.subcomponent = l.subcomponent;
063                this.componentLevel = l.componentLevel;
064        }
065
066        public Collection<GroupLocation> getGroups() {
067                return Collections.unmodifiableCollection(groups);
068        }
069        
070        public boolean isUnknown() {
071            return this == UNKNOWN;
072        }
073
074    public Location pushGroup(String name, int rep) {
075        groups.push(new Location.GroupLocation(name, rep));
076        return this;
077    }
078
079    public GroupLocation popGroup() {
080        return groups.pop();
081    }
082
083    public GroupLocation getGroupLocation() {
084        return groups.peek();
085    }
086
087        public String getSegmentName() {
088                return segmentName;
089        }
090
091        public Location withSegmentName(String segmentName) {
092                this.segmentName = segmentName;
093                return this;
094        }
095
096    public boolean isComponentLevel() {
097        return componentLevel;
098    }
099
100    public Location atComponentLevel(boolean componentLevel) {
101        this.componentLevel = componentLevel;
102        return this;
103    }
104
105        public int getSegmentRepetition() {
106                return segmentRepetition;
107        }
108
109        public Location withSegmentRepetition(int segmentRepetition) {
110                this.segmentRepetition = segmentRepetition;
111                return this;
112        }
113
114        public int getField() {
115                return field;
116        }
117
118        public Location withField(int field) {
119                this.field = field;
120                return this;
121        }
122
123        public int getFieldRepetition() {
124                return fieldRepetition;
125        }
126
127        public Location withFieldRepetition(int fieldRepetition) {
128                this.fieldRepetition = fieldRepetition;
129                return this;
130        }
131
132        public int getComponent() {
133                return component;
134        }
135
136        public Location withComponent(int component) {
137                this.component = component;
138                return this;
139        }
140
141        public int getSubcomponent() {
142                return subcomponent;
143        }
144
145        public Location withSubcomponent(int subcomponent) {
146                this.subcomponent = subcomponent;
147                return this;
148        }
149
150        /**
151         * Bulk setter for field indices
152         * 
153         * @param indices integer array as returned by Terser#getIndices
154         */
155        public Location withFieldIndizes(int[] indices) {
156                field = indices[0];
157                fieldRepetition = indices[1];
158                component = indices[2];
159                subcomponent = indices[3];
160                return this;
161        }
162
163
164        
165        @Override
166        public String toString() {
167                StringBuilder sb = new StringBuilder();
168        if (!groups.isEmpty()) {
169            sb.append('/');
170            for (GroupLocation gl : groups) {
171                sb.append(gl.groupName);
172                if (gl.repetition >= 0) {
173                    sb.append('(')
174                    .append(gl.repetition)
175                    .append(")");
176                }
177                sb.append("/");
178            }
179        }
180                if (segmentName != null) {
181                        sb.append(segmentName);
182                        if (segmentRepetition > 0) {
183                                sb.append("(").append(segmentRepetition).append(")");
184                        }
185                        if (field > 0) {
186                                sb.append("-").append(field);
187                                if (fieldRepetition >= 0) {
188                                        sb.append("(").append(fieldRepetition).append(")");
189                                }
190                                if (component > 0) {
191                                        sb.append("-").append(component);
192                                        if (subcomponent > 0) {
193                                                sb.append("-").append(subcomponent);
194                                        }
195                                }
196                        }
197                } else {
198                        if (sb.length() == 0) sb.append("unknown location");
199                }
200                return sb.toString();
201        }
202
203        @Override
204        public int hashCode() {
205                final int prime = 31;
206                int result = 1;
207        result = prime * result + ((groups == null) ? 0 : groups.hashCode());
208                result = prime * result + component;
209                result = prime * result + field;
210                result = prime * result + fieldRepetition;
211                result = prime * result + ((segmentName == null) ? 0 : segmentName.hashCode());
212                result = prime * result + segmentRepetition;
213                result = prime * result + subcomponent;
214                return result;
215        }
216
217        @Override
218        public boolean equals(Object obj) {
219                if (this == obj)
220                        return true;
221                if (obj == null)
222                        return false;
223                if (getClass() != obj.getClass())
224                        return false;
225                Location other = (Location) obj;
226                if (groups == null) {
227                    if (other.groups != null)
228                        return false;
229                } else if (!groups.equals(other.groups))
230                    return false;
231                if (component != other.component)
232                        return false;
233                if (field != other.field)
234                        return false;
235                if (fieldRepetition != other.fieldRepetition)
236                        return false;
237                if (segmentName == null) {
238                        if (other.segmentName != null)
239                                return false;
240                } else if (!segmentName.equals(other.segmentName))
241                        return false;
242                if (segmentRepetition != other.segmentRepetition)
243                        return false;
244        return subcomponent == other.subcomponent;
245    }
246
247    public static class GroupLocation {
248        final String groupName;
249        final int repetition;
250
251        private GroupLocation(String groupName, int repetition) {
252            this.groupName = groupName;
253            this.repetition = repetition;
254        }
255
256        public String getGroupName() {
257            return groupName;
258        }
259
260        public int getRepetition() {
261            return repetition;
262        }
263    }
264
265}