/* * Copyright 2001-2013 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") */ package com.uwyn.rife.datastructures; import com.uwyn.rife.tools.Sort; import com.uwyn.rife.tools.StringUtils; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class KeyValueList implements Collection, Cloneable { ArrayList<KeyValue> elements = null; public KeyValueList() { elements = new ArrayList<>(); } synchronized public void swap(int position1, int position2) { KeyValue element1 = this.get(position1); KeyValue element2 = this.get(position2); this.add(position1 + 1, element2); this.remove(position1); this.add(position2 + 1, element1); this.remove(position2); } synchronized public void sortKeys() { (new SortKeys()).sort(this, this.size() - 1, true); } synchronized public void sortValues() { (new SortValues()).sort(this, this.size() - 1, true); } public String getValue(String key) { KeyValue element = get(key); if (null == element) { return null; } else { return element.getValue(); } } public synchronized KeyValue getPrevious(int elementIndex) { if (-1 != elementIndex && elementIndex > 0) { return get(elementIndex - 1); } else { return null; } } public KeyValue getPrevious(String key) { return getPrevious(indexOf(key)); } public KeyValue getPrevious(KeyValue element) { return getPrevious(indexOf(element)); } public KeyValue getNext(int elementIndex) { if (-1 != elementIndex && elementIndex < size() - 1) { return get(elementIndex + 1); } else { return null; } } public KeyValue getNext(String key) { return getNext(indexOf(key)); } public KeyValue getNext(KeyValue element) { return getNext(indexOf(element)); } public synchronized Collection<KeyValue> getAll(String key) { ArrayList<KeyValue> matched_elements = new ArrayList<>(); KeyValue[] element_array = new KeyValue[size()]; toArray(element_array); int index = 0; do { index = indexOf(index, key); if (-1 != index) { matched_elements.add(element_array[index]); } } while (-1 != index); if (matched_elements.isEmpty()) { return null; } else { return matched_elements; } } public boolean contains(String key) { if (!elements.isEmpty()) { for (KeyValue element : elements) { if (element.getKey().equals(key)) { return true; } } } return false; } public boolean contains(Object keyvalue) { return null != keyvalue && keyvalue instanceof KeyValue && elements.contains(keyvalue); } public boolean contains(String key, String value) { return elements.contains(new KeyValue(key, value)); } public boolean contains(KeyValue element) { return elements.contains(element); } public boolean containsAll(Collection collection) { return elements.containsAll(collection); } public int indexOf(String key, String value) { return elements.indexOf(new KeyValue(key, value)); } public int indexOf(KeyValue element) { return elements.indexOf(element); } public synchronized int indexOf(int startIndex, KeyValue element) { if (!elements.isEmpty()) { for (int i = startIndex; i < elements.size(); i++) { if (elements.get(i).equals(element)) { return i; } } } return -1; } public synchronized int indexOf(String key) { return indexOf(0, key); } public synchronized int indexOf(int startIndex, String key) { if (!elements.isEmpty()) { for (int i = startIndex; i < elements.size(); i++) { if (elements.get(i).getKey().equals(key)) { return i; } } } return -1; } public synchronized boolean add(Object element) { return element instanceof KeyValue && add((KeyValue)element); } public synchronized boolean add(String key, String value) { return elements.add(new KeyValue(key, value)); } public synchronized boolean add(KeyValue element) { return elements.add(element); } public synchronized boolean add(KeyValueList source) { boolean result = true; for (Object element : source) { if (!add(((KeyValue)element).clone())) { result = false; } } return result; } public synchronized void add(int index, String key, String value) { elements.add(index, new KeyValue(key, value)); } public synchronized void add(int index, KeyValue element) { elements.add(index, element); } public boolean addAll(Collection collection) { boolean result = true; for (Object element : collection) { if (!add(element)) { result = false; } } return result; } public synchronized void addAfter(KeyValue existingElement, String key, String value) { elements.add(indexOf(existingElement) + 1, new KeyValue(key, value)); } public synchronized void addAfter(KeyValue existingElement, KeyValue newElement) { elements.add(indexOf(existingElement) + 1, newElement); } public synchronized void addBefore(KeyValue existingElement, String key, String value) { elements.add(indexOf(existingElement), new KeyValue(key, value)); } public synchronized void addBefore(KeyValue existingElement, KeyValue newElement) { elements.add(indexOf(existingElement), newElement); } public synchronized boolean remove(Object element) { return element instanceof KeyValue && remove((KeyValue)element); } public synchronized boolean remove(String key, String value) { return elements.remove(new KeyValue(key, value)); } public synchronized boolean remove(KeyValue element) { return elements.remove(element); } public synchronized void remove(int index) { elements.remove(index); } public boolean removeAll(Collection collection) { return elements.removeAll(collection); } public boolean retainAll(Collection collection) { return elements.retainAll(collection); } public synchronized boolean remove(String key) { if (!elements.isEmpty()) { for (KeyValue element : elements) { if (element.getKey().equals(key)) { return elements.remove(element); } } } return false; } public void clear() { elements.clear(); } public synchronized Object[] toArray() { return elements.toArray(); } public synchronized Object[] toArray(Object anArray[]) { elements.toArray(anArray); return anArray; } public synchronized String[] getKeysArray() { String[] keys = new String[size()]; int i = 0; for (Object key : keys()) { keys[i] = (String)key; i++; } return keys; } public synchronized void trimToSize() { elements.trimToSize(); } public synchronized void ensureCapacity(int minCapacity) { elements.ensureCapacity(minCapacity); } public int size() { return elements.size(); } public synchronized void setSize(int newSize) { if (size() > newSize) { ArrayList<KeyValue> new_elements = new ArrayList<>(newSize); for (int i = 0; i < newSize; i++) { new_elements.set(i, elements.get(i)); } elements = new_elements; } } public boolean isEmpty() { return elements.isEmpty(); } public synchronized Iterator<KeyValue> iterator() { return elements.iterator(); } public synchronized Collection<String> keys() { ArrayList<String> keys = new ArrayList<>(); for (KeyValue element : elements) { keys.add(element.getKey()); } return keys; } public synchronized Collection<String> values() { ArrayList<String> values = new ArrayList<>(); for (KeyValue element : elements) { values.add(element.getValue()); } return values; } public synchronized KeyValue get(int index) { return elements.get(index); } public synchronized KeyValue get(String key) { int index = indexOf(key); if (-1 == index) { return null; } else { return get(index); } } public synchronized KeyValue first() { return elements.get(0); } public synchronized KeyValue last() { return elements.get(size() - 1); } public synchronized void set(int index, String key, String value) { elements.set(index, new KeyValue(key, value)); } public synchronized void set(int index, KeyValue element) { elements.set(index, element); } public synchronized KeyValueList clone() { KeyValueList new_object; try { new_object = (KeyValueList)super.clone(); if (null != new_object.elements) { new_object.elements = (ArrayList<KeyValue>)elements.clone(); for (int i = 0; i < elements.size(); i++) { new_object.elements.set(i, elements.get(i).clone()); } } } catch (CloneNotSupportedException e) { new_object = null; } return new_object; } public String toHtml() { StringBuilder html = new StringBuilder(); if (!elements.isEmpty()) { for (KeyValue element : elements) { html.append("<b>").append(StringUtils.encodeHtml(element.getKey())).append("</b> = "").append(StringUtils.encodeHtml(element.getValue())).append(""<br/>\n"); } } return html.toString(); } public String toString() { StringBuilder output = new StringBuilder(); if (!elements.isEmpty()) { for (KeyValue element : elements) { output.append(element.getValue()).append(" "); } } return output.toString(); } public String toStringVerbose() { StringBuilder html = new StringBuilder(); if (!elements.isEmpty()) { for (KeyValue element : elements) { html.append(element.getKey()).append(" = \"").append(element.getValue()).append("\"\n"); } } return html.toString(); } private class SortKeys extends Sort { public void swap(Object dataToSort, int position1, int position2) { ((KeyValueList)dataToSort).swap(position1, position2); } public Object elementAt(Object dataToSort, int position) { return ((KeyValueList)dataToSort).get(position).getKey(); } public int compare(Object element1, Object element2) { return ((String)element1).compareTo((String)element2); } } private class SortValues extends Sort { public void swap(Object dataToSort, int position1, int position2) { ((KeyValueList)dataToSort).swap(position1, position2); } public Object elementAt(Object dataToSort, int position) { return ((KeyValueList)dataToSort).get(position).getValue(); } public int compare(Object element1, Object element2) { return ((String)element1).compareTo((String)element2); } } }