@Override
 public TagsList clone() {
   TagsList replicant = new TagsList();
   Iterator<QueryTag> tagsIter = tags.iterator();
   while (tagsIter.hasNext()) {
     QueryTag sourceElement = tagsIter.next();
     replicant.append(new QueryTag(sourceElement.getTagText(), sourceElement.getTagWeight()));
   }
   return replicant;
 }
 /**
  * Normalizes tags list via removing tags with zero weight, deleting duplicates and converting
  * tags text to lower case.
  */
 public QueryTag[] getNormalizedTagsArray() {
   Map<String, Boolean> seen = new HashMap<>();
   List<QueryTag> normalizedTagsList = new ArrayList<>(tags.size());
   ListIterator<QueryTag> iterator = tags.listIterator(tags.size());
   while (iterator.hasPrevious()) {
     QueryTag t = iterator.previous();
     String lowerTagText = t.getTagText().toLowerCase();
     if (t.getTagWeight() != 0 && seen.putIfAbsent(lowerTagText, Boolean.TRUE) == null) {
       normalizedTagsList.add(t);
     }
   }
   return normalizedTagsList.toArray(new QueryTag[normalizedTagsList.size()]);
 }
 /**
  * Calculates hash for storing in database and determining uniqueness.
  *
  * @return the calculated hash
  */
 public static long calculateHash(QueryTag[] tagsArray) {
   long hash = 1;
   for (QueryTag t : tagsArray) hash = 31 * hash + t.hashCode();
   return hash;
 }
 /**
  * Calculates hash for storing in database and determining uniqueness.
  *
  * @return the calculated hash
  */
 public long calculateHash() {
   long hash = 1;
   for (QueryTag t : tags) hash = 31 * hash + t.hashCode();
   return hash;
 }