package com.revolsys.identifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
import com.revolsys.collection.map.Maps;
import com.revolsys.collection.set.Sets;
import com.revolsys.datatype.DataTypes;
import com.revolsys.record.Record;
import com.revolsys.util.CompareUtil;
import com.revolsys.util.number.Numbers;
public interface Identifier {
Identifier NULL = new SingleIdentifier(null);
static Comparator<Identifier> comparator() {
return (identifier1, identifier2) -> {
if (identifier1 == identifier2) {
return 0;
} else if (identifier1 == null) {
return 1;
} else {
return identifier1.compareTo(identifier2);
}
};
}
/**
* Check that the two identifiers are equal. If either are null then false will be returned.
*
* @param identifier1
* @param identifier2
* @return True if the identifiers are not null and are equal. False otherwise.
*/
static boolean equals(final Identifier identifier1, final Identifier identifier2) {
if (identifier1 == null) {
return false;
} else if (identifier2 == null) {
return false;
} else {
return identifier1.equals(identifier2);
}
}
static Identifier newIdentifier(final Object... values) {
if (values == null || values.length == 0) {
return null;
} else if (values.length == 1) {
final Object value = values[0];
return newIdentifier(value);
} else {
return new ListIdentifier(values);
}
}
static Identifier newIdentifier(final Object value) {
if (value == null) {
return null;
} else if (value instanceof Long) {
final long longValue = (Long)value;
if (longValue < Integer.MIN_VALUE || longValue > Integer.MAX_VALUE) {
return new LongIdentifier(longValue);
} else {
final int intValue = (int)longValue;
return new IntegerIdentifier(intValue);
}
} else if (Numbers.isPrimitiveIntegral(value)) {
final Number number = (Number)value;
final int intValue = number.intValue();
return new IntegerIdentifier(intValue);
} else if (value instanceof Identifier) {
return (Identifier)value;
} else if (value instanceof Collection) {
final Collection<?> idValues = (Collection<?>)value;
return new ListIdentifier(idValues);
} else {
return new SingleIdentifier(value);
}
}
static <V> TreeMap<Identifier, V> newTreeMap() {
return new TreeMap<>(comparator());
}
static <V> Map<Identifier, V> newTreeMap(final Map<Identifier, ? extends V> map) {
return Maps.newTree(comparator(), map);
}
static TreeSet<Identifier> newTreeSet() {
return new TreeSet<>(comparator());
}
static TreeSet<Identifier> newTreeSet(final Iterable<Identifier> values) {
return Sets.newTree(comparator(), values);
}
static void setIdentifier(final Map<String, Object> record, final List<String> idFieldNames,
final Identifier identifier) {
if (identifier == null) {
for (int i = 0; i < idFieldNames.size(); i++) {
final String fieldName = idFieldNames.get(0);
record.put(fieldName, null);
}
} else {
identifier.setIdentifier(record, idFieldNames);
}
}
default int compareTo(final Identifier identifier2) {
if (identifier2 == this) {
return 0;
} else if (identifier2 == null) {
return -1;
} else {
final Iterator<Object> valueIter1 = getValues().iterator();
final Iterator<Object> valueIter2 = identifier2.getValues().iterator();
while (valueIter1.hasNext() && valueIter2.hasNext()) {
final Object value1 = valueIter1.next();
final Object value2 = valueIter2.next();
final int compare = CompareUtil.compare(value1, value2);
if (compare != 0) {
return compare;
}
}
if (valueIter1.hasNext()) {
return 1;
} else if (valueIter2.hasNext()) {
return -1;
} else {
return 0;
}
}
}
default Integer getInteger(final int index) {
final Object value = getValue(index);
if (value == null) {
return null;
} else if (value instanceof Number) {
final Number number = (Number)value;
return number.intValue();
} else {
return Integer.valueOf(value.toString());
}
}
default Long getLong(final int index) {
final Object value = getValue(index);
if (value == null) {
return null;
} else if (value instanceof Number) {
final Number number = (Number)value;
return number.longValue();
} else {
return Long.valueOf(value.toString());
}
}
default String getString(final int index) {
final Object value = getValue(index);
if (value == null) {
return null;
} else {
return DataTypes.toString(value);
}
}
@SuppressWarnings("unchecked")
default <V> V getValue(final int index) {
return (V)getValues().get(index);
}
List<Object> getValues();
default boolean isSingle() {
return getValues().size() == 1;
}
default void setIdentifier(final Map<String, Object> record, final List<String> fieldNames) {
final List<Object> values = getValues();
if (fieldNames.size() == values.size()) {
for (int i = 0; i < fieldNames.size(); i++) {
final String fieldName = fieldNames.get(i);
final Object value = values.get(i);
record.put(fieldName, value);
}
} else {
throw new IllegalArgumentException(
"Field names count for " + fieldNames + " != count for values " + values);
}
}
default void setIdentifier(final Map<String, Object> record, final String... fieldNames) {
setIdentifier(record, Arrays.asList(fieldNames));
}
default void setIdentifier(final Record record) {
setIdentifier(record, record.getRecordDefinition().getFieldNames());
}
@SuppressWarnings("unchecked")
default <V> V toSingleValue() {
final List<Object> values = getValues();
if (values.size() == 0) {
return null;
} else if (values.size() == 1) {
return (V)values.get(0);
} else {
throw new IllegalArgumentException(
"Cannot create value for identifier with multiple parts " + this);
}
}
}