001package ca.uhn.fhir.model.api; 002 003/* 004 * #%L 005 * HAPI FHIR - Core Library 006 * %% 007 * Copyright (C) 2014 - 2016 University Health Network 008 * %% 009 * Licensed under the Apache License, Version 2.0 (the "License"); 010 * you may not use this file except in compliance with the License. 011 * You may obtain a copy of the License at 012 * 013 * http://www.apache.org/licenses/LICENSE-2.0 014 * 015 * Unless required by applicable law or agreed to in writing, software 016 * distributed under the License is distributed on an "AS IS" BASIS, 017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 018 * See the License for the specific language governing permissions and 019 * limitations under the License. 020 * #L% 021 */ 022 023import java.io.Serializable; 024import java.util.ArrayList; 025import java.util.Collection; 026import java.util.Iterator; 027import java.util.LinkedHashSet; 028import java.util.List; 029import java.util.Set; 030 031import org.hl7.fhir.instance.model.api.IBase; 032 033/** 034 * A collection of tags present on a single resource. TagList is backed by a {@link LinkedHashSet}, so the order of 035 * added tags will be consistent, but duplicates will not be preserved. 036 * 037 * <p> 038 * <b>Thread safety:</b> This class is not thread safe 039 * </p> 040 */ 041public class TagList implements Set<Tag>, Serializable, IBase { 042 043 public static final String ATTR_CATEGORY = "category"; 044 public static final String ELEMENT_NAME = "TagList"; 045 046 public static final String ELEMENT_NAME_LC = ELEMENT_NAME.toLowerCase(); 047 private static final long serialVersionUID = 1L; 048 private transient List<Tag> myOrderedTags; 049 private LinkedHashSet<Tag> myTagSet = new LinkedHashSet<Tag>(); 050 051 /** 052 * Constructor 053 */ 054 public TagList() { 055 super(); 056 } 057 058 /** 059 * Copy constructor 060 */ 061 public TagList(TagList theTags) { 062 if (theTags != null) { 063 for (Tag next : theTags) { 064 add(next); 065 } 066 } 067 } 068 069 @Override 070 public String toString() { 071 StringBuilder b = new StringBuilder(); 072 b.append("TagList[").append(size()).append(" tag(s)]"); 073 for (Tag next : this) { 074 b.append("\n * ").append(next.toString()); 075 } 076 return b.toString(); 077 } 078 079 @Override 080 public boolean add(Tag theE) { 081 myOrderedTags = null; 082 return myTagSet.add(theE); 083 } 084 085 @Override 086 public boolean addAll(Collection<? extends Tag> theC) { 087 myOrderedTags = null; 088 return myTagSet.addAll(theC); 089 } 090 091 /** 092 * @deprecated Tags wil become immutable in a future release of HAPI, so {@link #addTag(String, String, String)} 093 * should be used instead 094 */ 095 @Deprecated 096 public Tag addTag() { 097 myOrderedTags = null; 098 return addTag(null, null, null); 099 } 100 101 /** 102 * Add a new tag instance 103 * 104 * @param theScheme 105 * The tag scheme 106 * @param theTerm 107 * The tag term 108 * @return Returns the newly created tag instance. Note that the tag is added to the list by this method, so you 109 * generally do not need to interact directly with the added tag. 110 */ 111 public Tag addTag(String theScheme, String theTerm) { 112 Tag retVal = new Tag(theScheme, theTerm); 113 add(retVal); 114 myOrderedTags = null; 115 return retVal; 116 } 117 118 /** 119 * Add a new tag instance 120 * 121 * @param theScheme 122 * The tag scheme 123 * @param theTerm 124 * The tag term 125 * @param theLabel 126 * The tag label 127 * @return Returns the newly created tag instance. Note that the tag is added to the list by this method, so you 128 * generally do not need to interact directly with the added tag. 129 */ 130 public Tag addTag(String theScheme, String theTerm, String theLabel) { 131 Tag retVal = new Tag(theScheme, theTerm, theLabel); 132 add(retVal); 133 myOrderedTags = null; 134 return retVal; 135 } 136 137 @Override 138 public void clear() { 139 myOrderedTags = null; 140 myTagSet.clear(); 141 } 142 143 @Override 144 public boolean contains(Object theO) { 145 return myTagSet.contains(theO); 146 } 147 148 @Override 149 public boolean containsAll(Collection<?> theC) { 150 return myTagSet.containsAll(theC); 151 } 152 153 @Override 154 public boolean equals(Object obj) { 155 if (this == obj) 156 return true; 157 if (obj == null) 158 return false; 159 if (getClass() != obj.getClass()) 160 return false; 161 TagList other = (TagList) obj; 162 if (myTagSet == null) { 163 if (other.myTagSet != null) 164 return false; 165 } else if (!myTagSet.equals(other.myTagSet)) 166 return false; 167 return true; 168 } 169 170 /** 171 * Returns the tag at a given index - Note that the TagList is backed by a {@link LinkedHashSet}, so the order of 172 * added tags will be consistent, but duplicates will not be preserved. 173 */ 174 public Tag get(int theIndex) { 175 if (myOrderedTags == null) { 176 myOrderedTags = new ArrayList<Tag>(); 177 for (Tag next : myTagSet) { 178 myOrderedTags.add(next); 179 } 180 } 181 return myOrderedTags.get(theIndex); 182 } 183 184 public Tag getTag(String theScheme, String theTerm) { 185 for (Tag next : this) { 186 if (theScheme.equals(next.getScheme()) && theTerm.equals(next.getTerm())) { 187 return next; 188 } 189 } 190 return null; 191 } 192 193 public List<Tag> getTagsWithScheme(String theScheme) { 194 ArrayList<Tag> retVal = new ArrayList<Tag>(); 195 for (Tag next : this) { 196 if (theScheme.equals(next.getScheme())) { 197 retVal.add(next); 198 } 199 } 200 return retVal; 201 } 202 203 @Override 204 public int hashCode() { 205 return myTagSet.hashCode(); 206 } 207 208 @Override 209 public boolean isEmpty() { 210 for (Tag next : myTagSet) { 211 if (next.isEmpty() == false) { 212 return false; 213 } 214 } 215 return true; 216 } 217 218 @Override 219 public Iterator<Tag> iterator() { 220 return myTagSet.iterator(); 221 } 222 223 @Override 224 public boolean remove(Object theO) { 225 myOrderedTags = null; 226 return myTagSet.remove(theO); 227 } 228 229 @Override 230 public boolean removeAll(Collection<?> theC) { 231 myOrderedTags = null; 232 return myTagSet.removeAll(theC); 233 } 234 235 @Override 236 public boolean retainAll(Collection<?> theC) { 237 myOrderedTags = null; 238 return myTagSet.retainAll(theC); 239 } 240 241 @Override 242 public int size() { 243 return myTagSet.size(); 244 } 245 246 @Override 247 public Object[] toArray() { 248 return myTagSet.toArray(); 249 } 250 251 @Override 252 public <T> T[] toArray(T[] theA) { 253 return myTagSet.toArray(theA); 254 } 255 256}