/*
* $Id$
* This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc
*
* Copyright (c) 2000-2012 Stephane GALLAND.
* Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports,
* Universite de Technologie de Belfort-Montbeliard.
* Copyright (c) 2013-2016 The original authors, and other authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.arakhne.afc.attrs.attr;
import static org.arakhne.afc.attrs.attr.AttributeConstants.DEFAULT_SCHEME;
import static org.arakhne.afc.attrs.attr.AttributeConstants.FALSE_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.F_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.NON_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.NO_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.N_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.OUI_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.O_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.TRUE_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.T_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.YES_CONSTANT;
import static org.arakhne.afc.attrs.attr.AttributeConstants.Y_CONSTANT;
import java.lang.reflect.Array;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.Locale;
import java.util.Objects;
import java.util.UUID;
import org.eclipse.xtext.xbase.lib.Pure;
import org.arakhne.afc.math.geometry.d2.Point2D;
import org.arakhne.afc.math.geometry.d2.Tuple2D;
import org.arakhne.afc.math.geometry.d2.d.Point2d;
import org.arakhne.afc.math.geometry.d3.Point3D;
import org.arakhne.afc.math.geometry.d3.Tuple3D;
import org.arakhne.afc.math.geometry.d3.d.Point3d;
import org.arakhne.afc.ui.vector.Color;
import org.arakhne.afc.ui.vector.Image;
import org.arakhne.afc.ui.vector.VectorToolkit;
import org.arakhne.afc.vmutil.ReflectionUtil;
/**
* This class contains an attribute value.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
@SuppressWarnings({"deprecation", "checkstyle:methodcount"})
public class AttributeValueImpl implements AttributeValue {
private static final long serialVersionUID = 4014368008512085546L;
private static final String UUID_STR = "uuid"; //$NON-NLS-1$
/**
* Type of the metadata.
*/
private AttributeType type;
/**
* Value of the metadata.
*/
private Object value;
/** Indicates if this attribute was assigned.
*/
private boolean assigned;
/**
* Uninitialized value.
*/
public AttributeValueImpl() {
this.type = AttributeType.OBJECT;
this.value = this.type.getDefaultValue();
}
/**
* Uninitialized value.
*
* @param type is the type of the value.
*/
public AttributeValueImpl(AttributeType type) {
this.type = type;
this.value = null;
this.assigned = false;
}
/**
* @param value is the value to initialize this new instance.
*/
public AttributeValueImpl(AttributeValue value) {
if (value != null) {
this.type = value.getType();
try {
this.value = value.getValue();
this.assigned = isNullAllowed() || (this.value != null);
} catch (AttributeException exception) {
this.value = null;
this.assigned = false;
}
} else {
this.value = null;
this.assigned = false;
}
}
/**
* @param type is the type of this value.
* @param rawValue is the value.
*/
public AttributeValueImpl(AttributeType type, Object rawValue) {
this.type = type;
if (rawValue == null) {
this.value = rawValue;
} else {
try {
this.value = type.cast(rawValue);
} catch (Exception exception) {
this.value = null;
}
}
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(boolean value) {
this.type = AttributeType.BOOLEAN;
this.value = new Boolean(value);
this.assigned = true;
}
/**
* @param value is the value.
* @deprecated No replacement
*/
@Deprecated
public AttributeValueImpl(Color value) {
this.type = AttributeType.COLOR;
this.value = (value != null) ? VectorToolkit.color(value.getRed(), value.getGreen(),
value.getBlue(), value.getAlpha()) : null;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(UUID value) {
this.type = AttributeType.UUID;
this.value = (value != null) ? new UUID(value.getMostSignificantBits(),
value.getLeastSignificantBits()) : null;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(URL value) {
this.type = AttributeType.URL;
try {
this.value = (value != null) ? new URL(value.toExternalForm()) : null;
} catch (MalformedURLException e) {
this.value = null;
}
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(URI value) {
this.type = AttributeType.URI;
try {
this.value = (value != null) ? new URI(value.toASCIIString()) : null;
} catch (URISyntaxException e) {
this.value = null;
}
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(InetAddress value) {
this.type = AttributeType.INET_ADDRESS;
this.value = (value != null) ? value : null;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(InetSocketAddress value) {
this.type = AttributeType.INET_ADDRESS;
this.value = (value != null) ? value.getAddress() : null;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(Enum<?> value) {
this.type = AttributeType.ENUMERATION;
this.value = (value != null) ? value : null;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(Class<?> value) {
this.type = AttributeType.TYPE;
this.value = (value != null) ? value : null;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(Date value) {
this.type = AttributeType.DATE;
this.value = (value != null) ? new Date(value.getTime()) : null;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(float value) {
this.type = AttributeType.REAL;
this.value = new Double(value);
this.assigned = true;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(double value) {
this.type = AttributeType.REAL;
this.value = new Double(value);
this.assigned = true;
}
/**
* @param value is the value.
* @deprecated no replacement.
*/
@Deprecated
public AttributeValueImpl(Image value) {
this.type = AttributeType.IMAGE;
this.value = value;
this.assigned = true;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(int value) {
this.type = AttributeType.INTEGER;
this.value = new Long(value);
this.assigned = true;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(long value) {
this.type = AttributeType.INTEGER;
this.value = new Long(value);
this.assigned = true;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(Point2D<?, ?> value) {
this.type = AttributeType.POINT;
this.value = value;
this.assigned = this.value != null;
}
/**
* @param x is the value.
* @param y is the value.
*/
public AttributeValueImpl(float x, float y) {
this.type = AttributeType.POINT;
this.value = new Point2d(x, y);
this.assigned = true;
}
/**
* @param x is the value.
* @param y is the value.
*/
public AttributeValueImpl(double x, double y) {
this.type = AttributeType.POINT;
this.value = new Point2d(x, y);
this.assigned = true;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(Point3D<?, ?> value) {
this.type = AttributeType.POINT3D;
this.value = value;
this.assigned = this.value != null;
}
/**
* @param x is the value.
* @param y is the value.
* @param z is the value.
*/
public AttributeValueImpl(float x, float y, float z) {
this.type = AttributeType.POINT3D;
this.value = new Point3d(x, y, z);
this.assigned = true;
}
/**
* @param x is the value.
* @param y is the value.
* @param z is the value.
*/
public AttributeValueImpl(double x, double y, double z) {
this.type = AttributeType.POINT3D;
this.value = new Point3d(x, y, z);
this.assigned = true;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(String value) {
this.type = AttributeType.STRING;
this.value = value;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(Point2D<?, ?>[] value) {
this.type = AttributeType.POLYLINE;
this.value = value;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(Point3D<?, ?>[] value) {
this.type = AttributeType.POLYLINE3D;
this.value = value;
this.assigned = this.value != null;
}
/**
* @param value is the value.
*/
public AttributeValueImpl(Object value) {
final AttributeType detectedType = AttributeType.fromValue(value);
this.type = detectedType;
this.value = detectedType.cast(value);
this.assigned = isNullAllowed() || (this.value != null);
}
/** Replies the best attribute value that is representing
* the given text.
*
* @param text the text.
* @return the attribute value, never <code>null</code>.
*/
@Pure
@SuppressWarnings("checkstyle:cyclomaticcomplexity")
public static AttributeValueImpl parse(String text) {
final AttributeValueImpl value = new AttributeValueImpl(text);
if (text != null && !text.isEmpty()) {
Object binValue;
for (final AttributeType type : AttributeType.values()) {
try {
binValue = null;
switch (type) {
case BOOLEAN:
binValue = value.getBoolean();
break;
case COLOR:
binValue = parseColor((String) value.value, true);
break;
case DATE:
binValue = value.getDate();
break;
case ENUMERATION:
binValue = value.getEnumeration();
break;
case IMAGE:
binValue = value.getImage();
break;
case INET_ADDRESS:
binValue = value.getInetAddress();
break;
case INTEGER:
binValue = value.getInteger();
break;
case OBJECT:
binValue = value.getJavaObject();
break;
case POINT:
binValue = parsePoint((String) value.value, true);
break;
case POINT3D:
binValue = parsePoint3D((String) value.value, true);
break;
case POLYLINE:
binValue = parsePolyline((String) value.value, true);
break;
case POLYLINE3D:
binValue = parsePolyline3D((String) value.value, true);
break;
case REAL:
binValue = value.getReal();
break;
case STRING:
binValue = value.getString();
break;
case TIMESTAMP:
binValue = value.getTimestamp();
break;
case TYPE:
binValue = value.getJavaClass();
break;
case URI:
binValue = parseURI((String) value.value);
break;
case URL:
binValue = value.getURL();
break;
case UUID:
binValue = parseUUID((String) value.value);
break;
default:
//
}
if (binValue != null) {
return new AttributeValueImpl(type, binValue);
}
} catch (Throwable exception) {
//
}
}
}
return value;
}
/** Compare the two specified values.
*
* @param arg0 first value.
* @param arg1 second value.
* @return replies a negative value if {@code arg0} is lesser than
* {@code arg1}, a positive value if {@code arg0} is greater than
* {@code arg1}, or <code>0</code> if they are equal.
* @see AttributeValueComparator
*/
@Pure
public static int compareValues(AttributeValue arg0, AttributeValue arg1) {
if (arg0 == arg1) {
return 0;
}
if (arg0 == null) {
return Integer.MAX_VALUE;
}
if (arg1 == null) {
return Integer.MIN_VALUE;
}
Object v0;
Object v1;
try {
v0 = arg0.getValue();
} catch (Exception exception) {
v0 = null;
}
try {
v1 = arg1.getValue();
} catch (Exception exception) {
v1 = null;
}
return compareRawValues(v0, v1);
}
/** Compare the internal objects of two specified values
*
* @param arg0 first value.
* @param arg1 second value.
* @return replies a negative value if {@code arg0} is lesser than
* {@code arg1}, a positive value if {@code arg0} is greater than
* {@code arg1}, or <code>0</code> if they are equal.
*/
@Pure
@SuppressWarnings({"unchecked", "rawtypes", "checkstyle:returncount", "checkstyle:npathcomplexity"})
private static int compareRawValues(Object arg0, Object arg1) {
if (arg0 == arg1) {
return 0;
}
if (arg0 == null) {
return Integer.MAX_VALUE;
}
if (arg1 == null) {
return Integer.MIN_VALUE;
}
if ((arg0 instanceof Number) && (arg1 instanceof Number)) {
return Double.compare(((Number) arg0).doubleValue(), ((Number) arg1).doubleValue());
}
try {
if (arg0 instanceof Comparable<?>) {
return ((Comparable) arg0).compareTo(arg1);
}
} catch (RuntimeException exception) {
//
}
try {
if (arg1 instanceof Comparable<?>) {
return -((Comparable) arg1).compareTo(arg0);
}
} catch (RuntimeException exception) {
//
}
if (arg0.equals(arg1)) {
return 0;
}
final String sv0 = arg0.toString();
final String sv1 = arg1.toString();
if (sv0 == sv1) {
return 0;
}
if (sv0 == null) {
return Integer.MAX_VALUE;
}
if (sv1 == null) {
return Integer.MIN_VALUE;
}
return sv0.compareTo(sv1);
}
@Pure
@Override
public boolean equals(Object obj) {
if (obj instanceof AttributeValue) {
return compareValues(this, (AttributeValue) obj) == 0;
}
return compareRawValues(this.value, obj) == 0;
}
@Pure
@Override
public int hashCode() {
return 31 + Objects.hashCode(this.value);
}
@Pure
@Override
public String toString() {
return ReflectionUtil.toString(this);
}
@Pure
@Override
public boolean isAssignableFrom(AttributeType type) {
return getType().isAssignableFrom(type);
}
@Pure
@Override
public boolean isAssignableFrom(AttributeValue value) {
return getType().isAssignableFrom(value.getType());
}
/** Replies if this value was assigned and
* supposes that the <code>null</code> value is
* allowed.
*
* @return <code>true</code> if the value is not assigned or equals to <code>null</code>.
*/
private boolean isNotAssignedOrNull() {
return !this.assigned || this.value == null;
}
/** Assert that the attribute value was assigned.
*/
private void assertAssigned() throws AttributeNotInitializedException {
if ((this.type == null) || (!this.assigned)) {
throw new AttributeNotInitializedException();
}
}
/** Assert that the attribute value was assigned and not <code>null</code>.
*
* @throws AttributeNotInitializedException attribute not initialized.
*/
protected void assertAssignedAndNotNull() throws AttributeNotInitializedException {
if ((this.type == null) || (!this.assigned) || (this.value == null)) {
throw new AttributeNotInitializedException();
}
}
@Pure
@Override
public boolean isBaseType() {
return this.type.isBaseType();
}
@Pure
@Override
public boolean isNullAllowed() {
return this.type.isNullAllowed();
}
@Pure
@Override
public AttributeType getType() {
return this.type;
}
@Override
@SuppressWarnings("checkstyle:cyclomaticcomplexity")
public void setType(AttributeType type) throws InvalidAttributeTypeException {
try {
switch (type) {
case INTEGER:
this.value = new Long(getInteger());
break;
case REAL:
this.value = new Double(getReal());
break;
case STRING:
this.value = getString();
break;
case BOOLEAN:
this.value = new Boolean(getBoolean());
break;
case DATE:
this.value = getDate();
break;
case TIMESTAMP:
this.value = new Timestamp(getTimestamp());
break;
case OBJECT:
this.value = getJavaObject();
break;
case POINT:
this.value = getPoint();
break;
case POINT3D:
this.value = getPoint3D();
break;
case COLOR:
this.value = getColor();
break;
case UUID:
this.value = getUUID();
break;
case IMAGE:
this.value = getImage();
break;
case POLYLINE:
this.value = getPolyline();
break;
case POLYLINE3D:
this.value = getPolyline3D();
break;
case URI:
this.value = getURI();
break;
case URL:
this.value = getURL();
break;
case INET_ADDRESS:
this.value = getInetAddress();
break;
case ENUMERATION:
this.value = getEnumeration();
break;
case TYPE:
this.value = getJavaClass();
break;
default:
throw new InvalidAttributeTypeException();
}
} catch (NumberFormatException ex) {
throw new InvalidAttributeTypeException();
} catch (AttributeNotInitializedException e) {
this.value = type.getDefaultValue();
}
this.type = type;
}
@Override
public boolean cast(AttributeType attrType) {
boolean b = true;
try {
setType(attrType);
} catch (InvalidAttributeTypeException ex) {
this.value = attrType.getDefaultValue();
b = false;
}
this.type = attrType;
return b;
}
@Override
public void castAndSet(AttributeType attrType, Object attrValue) {
try {
if (attrValue instanceof AttributeValue) {
this.type = ((AttributeValue) attrValue).getType();
try {
this.value = ((AttributeValue) attrValue).getValue();
this.assigned = true;
} catch (AttributeNotInitializedException e) {
this.value = attrType.getDefaultValue();
this.assigned = true;
}
} else {
this.type = attrType;
this.value = attrType.cast(attrValue);
this.assigned = true;
}
if (attrValue != null) {
setType(attrType);
} else {
this.value = attrType.getDefaultValue();
this.assigned = true;
}
} catch (InvalidAttributeTypeException ex) {
this.value = attrType.getDefaultValue();
this.assigned = true;
}
}
@Pure
@Override
public Object getValue() throws InvalidAttributeTypeException, AttributeNotInitializedException {
assertAssigned();
return this.value;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity"})
public final Class<?> getInternalStorageType() {
switch (this.type) {
case BOOLEAN:
return Boolean.class;
case COLOR:
return Color.class;
case DATE:
return Date.class;
case ENUMERATION:
return Enum.class;
case IMAGE:
return Image.class;
case INET_ADDRESS:
return InetAddress.class;
case INTEGER:
return Long.class;
case OBJECT:
return Object.class;
case POINT:
return Point2D.class;
case POINT3D:
return Point3D.class;
case POLYLINE:
return Point2D[].class;
case POLYLINE3D:
return Point3D[].class;
case REAL:
return Double.class;
case STRING:
return String.class;
case TIMESTAMP:
return Timestamp.class;
case TYPE:
return Class.class;
case URI:
return URI.class;
case URL:
return URL.class;
case UUID:
return UUID.class;
default:
}
return null;
}
@Override
public void setValue(AttributeValue value) {
this.type = value.getType();
try {
this.assigned = value.isAssigned();
this.value = value.getValue();
} catch (AttributeException e) {
this.value = this.type.getDefaultValue();
}
}
@Override
public void setValue(Object value) {
final AttributeType detectedType = AttributeType.fromValue(value);
this.value = detectedType.cast(value);
this.assigned = this.value != null;
}
/** Set this value with the content of the specified one.
*
* <p>The type of the attribute will be NOT detected from the type
* of the object. It means that it is not changed by this function.
* The given value must be compatible with internal representation
* of the attribute implementation.
*
* @param value is the raw value to put inside this attribute value.
*/
protected void setInternalValue(Object value) {
this.value = value;
this.assigned = this.value != null;
}
/** Set this value with the content of the specified one.
*
* <p>The type of the attribute will be NOT detected from the type
* of the object. It means that it will be equal to the given type,
* even if the given value is incompatible.
* The given value must be compatible with internal representation
* of the attribute implementation.
*
* @param value is the raw value to put inside this attribute value.
* @param type is the type of the value.
*/
protected void setInternalValue(Object value, AttributeType type) {
this.value = value;
this.assigned = this.value != null;
this.type = type;
}
@Override
public void setToDefault() {
this.assigned = true;
this.value = this.type.getDefaultValue();
}
@Override
public void setToDefaultIfUninitialized() {
if (!isAssigned()) {
setToDefault();
}
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity"})
public long getInteger() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case INTEGER:
return ((Long) this.value).longValue();
case TIMESTAMP:
return ((Timestamp) this.value).longValue();
case REAL:
return ((Double) this.value).longValue();
case STRING:
return Long.parseLong((String) this.value);
case DATE:
return ((Date) this.value).getTime();
case BOOLEAN:
return ((Boolean) this.value).booleanValue() ? 1 : 0;
case COLOR:
return ((Color) this.value).getRGB();
case OBJECT:
if (this.value instanceof Number) {
return ((Number) this.value).longValue();
}
break;
case ENUMERATION:
if (this.value instanceof Enum<?>) {
return ((Enum<?>) this.value).ordinal();
}
break;
case IMAGE:
case POINT:
case POINT3D:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case TYPE:
break;
default:
throw new InvalidAttributeTypeException();
}
} catch (NumberFormatException exception) {
//
}
throw new InvalidAttributeTypeException();
}
@Override
public void setInteger(int value) {
this.value = new Long(value);
this.type = AttributeType.INTEGER;
this.assigned = true;
}
@Override
public void setInteger(long value) {
this.value = new Long(value);
this.type = AttributeType.INTEGER;
this.assigned = true;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity"})
public double getReal() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case INTEGER:
return ((Long) this.value).doubleValue();
case TIMESTAMP:
return ((Timestamp) this.value).doubleValue();
case REAL:
return ((Double) this.value).doubleValue();
case STRING:
return Double.parseDouble((String) this.value);
case DATE:
return ((Date) this.value).getTime();
case BOOLEAN:
return ((Boolean) this.value).booleanValue() ? 1. : 0.;
case COLOR:
return ((Color) this.value).getRGB();
case OBJECT:
if (this.value instanceof Number) {
return ((Number) this.value).doubleValue();
}
break;
case ENUMERATION:
if (this.value instanceof Enum<?>) {
return ((Enum<?>) this.value).ordinal();
}
break;
case IMAGE:
case POINT:
case POINT3D:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case TYPE:
default:
throw new InvalidAttributeTypeException();
}
} catch (ClassCastException | NumberFormatException exception) {
//
}
throw new InvalidAttributeTypeException();
}
@Override
public void setReal(double value) {
this.value = new Double(value);
this.type = AttributeType.REAL;
this.assigned = true;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity"})
public String getString() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case STRING:
return (String) this.value;
case BOOLEAN:
return ((Boolean) this.value).toString();
case COLOR:
final Color col = (Color) this.value;
return Integer.toString(col.getRed())
+ ';' + col.getGreen()
+ ';' + col.getBlue()
+ ';' + col.getAlpha();
case UUID:
final UUID uuid = (UUID) this.value;
return uuid.toString();
case URL:
final URL url = (URL) this.value;
return url.toExternalForm();
case URI:
final URI uri = (URI) this.value;
return uri.toASCIIString();
case TIMESTAMP:
final SimpleDateFormat tmformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //$NON-NLS-1$
return tmformat.format(new Date(((Timestamp) this.value).longValue()));
case INTEGER:
return ((Long) this.value).toString();
case REAL:
return ((Double) this.value).toString();
case POINT:
return getStringFromPoint();
case POINT3D:
return getStringFromPoint3D();
case DATE:
final SimpleDateFormat dtformat = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
return dtformat.format((Date) this.value);
case POLYLINE:
return getStringFromPolyline();
case POLYLINE3D:
return getStringFromPolyline3D();
case ENUMERATION:
return getStringFromEnumeration();
case TYPE:
return ((Class<?>) this.value).getCanonicalName();
case INET_ADDRESS:
case OBJECT:
case IMAGE:
return this.value.toString();
default:
throw new InvalidAttributeTypeException();
}
} catch (ClassCastException exception) {
//
}
throw new InvalidAttributeTypeException();
}
private String getStringFromPoint() {
final Point2D<?, ?> pt2 = (Point2D<?, ?>) this.value;
final StringBuilder buffer1 = new StringBuilder();
buffer1.append(pt2.getX());
buffer1.append(";"); //$NON-NLS-1$
buffer1.append(pt2.getY());
return buffer1.toString();
}
private String getStringFromPoint3D() {
final Point3D<?, ?> pt3 = (Point3D<?, ?>) this.value;
final StringBuilder buffer2 = new StringBuilder();
buffer2.append(pt3.getX());
buffer2.append(";"); //$NON-NLS-1$
buffer2.append(pt3.getY());
buffer2.append(";"); //$NON-NLS-1$
buffer2.append(pt3.getZ());
return buffer2.toString();
}
private String getStringFromPolyline() {
final StringBuilder buffer3 = new StringBuilder();
final Point2D<?, ?>[] lstpt2 = (Point2D<?, ?>[]) this.value;
for (int i = 0; i < lstpt2.length; ++i) {
if (lstpt2[i] != null) {
if (buffer3.length() > 0) {
buffer3.append(";"); //$NON-NLS-1$
}
buffer3.append(lstpt2[i].getX());
buffer3.append(";"); //$NON-NLS-1$
buffer3.append(lstpt2[i].getY());
}
}
return buffer3.toString();
}
private String getStringFromPolyline3D() {
final StringBuilder buffer4 = new StringBuilder();
final Point3D<?, ?>[] lstpt3 = (Point3D<?, ?>[]) this.value;
for (int i = 0; i < lstpt3.length; ++i) {
if (lstpt3[i] != null) {
if (buffer4.length() > 0) {
buffer4.append(";"); //$NON-NLS-1$
}
buffer4.append(lstpt3[i].getX());
buffer4.append(";"); //$NON-NLS-1$
buffer4.append(lstpt3[i].getY());
buffer4.append(";"); //$NON-NLS-1$
buffer4.append(lstpt3[i].getZ());
}
}
return buffer4.toString();
}
private String getStringFromEnumeration() {
final StringBuilder buffer5 = new StringBuilder();
final Enum<?> enumeration = (Enum<?>) this.value;
final Class<?> enumerationType = enumeration.getDeclaringClass();
final String typeName = enumerationType.getCanonicalName();
buffer5.append(typeName);
buffer5.append("."); //$NON-NLS-1$
buffer5.append(((Enum<?>) this.value).name());
return buffer5.toString();
}
@Override
public void setString(String value) {
this.value = value;
this.type = AttributeType.STRING;
this.assigned = this.value != null;
}
/** Parse a date according to the specified locale.
*/
private static Date extractDate(String text, Locale locale) {
DateFormat fmt;
for (int style = 0; style <= 3; ++style) {
// Date and time parsing
for (int style2 = 0; style2 <= 3; ++style2) {
fmt = DateFormat.getDateTimeInstance(style, style2, locale);
try {
return fmt.parse(text);
} catch (ParseException exception) {
//
}
}
// Date only parsing
fmt = DateFormat.getDateInstance(style, locale);
try {
return fmt.parse(text);
} catch (ParseException exception) {
//
}
// Time only parsing
fmt = DateFormat.getTimeInstance(style, locale);
try {
return fmt.parse(text);
} catch (ParseException exception) {
//
}
}
return null;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity", "checkstyle:npathcomplexity"})
public Date getDate() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case DATE:
return (Date) ((Date) this.value).clone();
case REAL:
return new Date(((Double) this.value).longValue());
case INTEGER:
return new Date(((Long) this.value).longValue());
case TIMESTAMP:
return new Date(((Timestamp) this.value).longValue());
case STRING:
return getDateFromString();
case OBJECT:
return getDateFromObject();
case BOOLEAN:
case COLOR:
case IMAGE:
case POINT:
case POINT3D:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
}
} catch (Exception e) {
//
}
throw new InvalidAttributeTypeException();
}
private Date getDateFromObject() throws InvalidAttributeTypeException {
if (this.value instanceof Date) {
return (Date) this.value;
}
if (this.value instanceof Calendar) {
return ((Calendar) this.value).getTime();
}
if (this.value instanceof Number) {
return new Date(((Number) this.value).longValue());
}
throw new InvalidAttributeTypeException();
}
private Date getDateFromString() throws Exception {
final String txt = (String) this.value;
DateFormat fmt;
Date dt;
dt = extractDate(txt, Locale.getDefault());
if (dt != null) {
return dt;
}
dt = extractDate(txt, Locale.US);
if (dt != null) {
return dt;
}
dt = extractDate(txt, Locale.UK);
if (dt != null) {
return dt;
}
try {
fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //$NON-NLS-1$
return fmt.parse(txt);
} catch (ParseException exception) {
//
}
fmt = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
return fmt.parse(txt);
}
@Override
public void setDate(Date value) {
this.value = value;
this.type = AttributeType.DATE;
this.assigned = this.value != null;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity", "checkstyle:npathcomplexity"})
public boolean getBoolean() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case BOOLEAN:
return ((Boolean) this.value).booleanValue();
case STRING:
return getBooleanFromString();
case INTEGER:
return ((Long) this.value).longValue() != 0;
case TIMESTAMP:
return ((Timestamp) this.value).longValue() != 0;
case REAL:
return ((Double) this.value).doubleValue() != 0.;
case OBJECT:
if (this.value instanceof Boolean) {
return ((Boolean) this.value).booleanValue();
}
break;
case COLOR:
case DATE:
case IMAGE:
case POINT:
case POINT3D:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException exception) {
//
}
throw new InvalidAttributeTypeException();
}
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity", "checkstyle:npathcomplexity"})
private boolean getBooleanFromString() throws InvalidAttributeTypeException {
// Do not use the function Boolean.parseBoolean() because
// it replies false when the string does not contains "true"
if (TRUE_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return true;
}
if (YES_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return true;
}
if (OUI_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return true;
}
if (T_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return true;
}
if (Y_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return true;
}
if (O_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return true;
}
if (FALSE_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return false;
}
if (NO_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return false;
}
if (NON_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return false;
}
if (F_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return false;
}
if (N_CONSTANT.compareToIgnoreCase((String) this.value) == 0) {
return false;
}
throw new InvalidAttributeTypeException();
}
@Override
public void setBoolean(boolean value) {
this.value = new Boolean(value);
this.type = AttributeType.BOOLEAN;
this.assigned = true;
}
@Pure
@Override
public boolean isObjectValue() {
return !isBaseType();
}
@Pure
@Override
@SuppressWarnings("unchecked")
public <T> T getJavaObject() throws InvalidAttributeTypeException, AttributeNotInitializedException {
if (!isObjectValue()) {
throw new InvalidAttributeTypeException();
}
if (isNotAssignedOrNull()) {
return null;
}
try {
return (T) this.value;
} catch (ClassCastException exception) {
throw new InvalidAttributeTypeException();
}
}
@Override
public void setJavaObject(Object value) {
this.value = value;
this.type = AttributeType.OBJECT;
this.assigned = true;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity", "checkstyle:npathcomplexity"})
public long getTimestamp() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case INTEGER:
return ((Long) this.value).longValue();
case TIMESTAMP:
return ((Timestamp) this.value).longValue();
case REAL:
return ((Double) this.value).longValue();
case STRING:
return Long.parseLong((String) this.value);
case DATE:
return ((Date) this.value).getTime();
case BOOLEAN:
return ((Boolean) this.value).booleanValue() ? 1 : 0;
case COLOR:
return ((Color) this.value).getRGB();
case OBJECT:
return getTimestampFromObject();
case IMAGE:
case POINT:
case POINT3D:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException | NumberFormatException exception) {
//
}
throw new InvalidAttributeTypeException();
}
private long getTimestampFromObject() throws InvalidAttributeTypeException {
if (this.value instanceof Number) {
return ((Number) this.value).longValue();
}
if (this.value instanceof Date) {
return ((Date) this.value).getTime();
}
if (this.value instanceof Calendar) {
return ((Calendar) this.value).getTimeInMillis();
}
throw new InvalidAttributeTypeException();
}
@Override
public void setTimestamp(long value) {
this.value = new Timestamp(value);
this.type = AttributeType.TIMESTAMP;
this.assigned = true;
}
private static Point3D<?, ?> parsePoint3D(String text, boolean isStrict) {
final String[] comp = text.split(";"); //$NON-NLS-1$
if (isStrict && comp.length != 3) {
return null;
}
final Point3D<?, ?> pt3 = new Point3d();
if (comp.length > 0) {
pt3.setX(Double.parseDouble(comp[0]));
}
if (comp.length > 1) {
pt3.setY(Double.parseDouble(comp[1]));
}
if (comp.length > 2) {
pt3.setZ(Double.parseDouble(comp[2]));
}
return pt3;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity"})
public Point3D<?, ?> getPoint3D() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case COLOR:
final Color col = (Color) this.value;
return new Point3d(col.getRed(), col.getGreen(), col.getBlue());
case REAL:
final Double flt = (Double) this.value;
return new Point3d(flt.doubleValue(), 0, 0);
case INTEGER:
final Long lg = (Long) this.value;
return new Point3d(lg.doubleValue(), 0, 0);
case TIMESTAMP:
final Timestamp ts = (Timestamp) this.value;
return new Point3d(ts.doubleValue(), 0, 0);
case DATE:
final Date dt = (Date) this.value;
return new Point3d(dt.getTime(), 0, 0);
case POINT:
final Point2D<?, ?> pt2 = (Point2D<?, ?>) this.value;
return new Point3d(pt2.getX(), pt2.getY(), 0);
case POINT3D:
return ((Point3D<?, ?>) this.value).clone();
case STRING:
return parsePoint3D((String) this.value, false);
case OBJECT:
return getPoint3DFromObject();
case BOOLEAN:
case IMAGE:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException exception) {
//
} catch (NumberFormatException exception) {
//
}
throw new InvalidAttributeTypeException();
}
private Point3D<?, ?> getPoint3DFromObject() {
if (this.value instanceof Tuple3D) {
final Tuple3D<?> t3 = (Tuple3D<?>) this.value;
return new Point3d(t3.getX(), t3.getY(), t3.getZ());
}
if (this.value instanceof Tuple2D) {
final Tuple2D<?> t2 = (Tuple2D<?>) this.value;
return new Point3d(t2.getX(), t2.getY(), 0);
}
return null;
}
@Override
public void setPoint3D(Point3D<?, ?> value) {
this.value = value;
this.type = AttributeType.POINT3D;
this.assigned = this.value != null;
}
@Override
public void setPoint3D(float x, float y, float z) {
this.value = new Point3d(x, y, z);
this.type = AttributeType.POINT3D;
this.assigned = true;
}
private static Point2D<?, ?> parsePoint(String text, boolean isStrict) {
final String[] comp = text.split(";"); //$NON-NLS-1$
if (isStrict && comp.length != 2) {
return null;
}
final double x;
final double y;
if (comp.length > 0) {
x = Double.parseDouble(comp[0]);
} else {
x = 0;
}
if (comp.length > 1) {
y = Double.parseDouble(comp[1]);
} else {
y = 0;
}
return new Point2d(x, y);
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity"})
public Point2D<?, ?> getPoint() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case COLOR:
final Color col = (Color) this.value;
return new Point2d(col.getRed(), col.getGreen());
case REAL:
final Double flt = (Double) this.value;
return new Point2d(flt.doubleValue(), 0);
case INTEGER:
final Long lg = (Long) this.value;
return new Point2d(lg.doubleValue(), 0);
case TIMESTAMP:
final Timestamp ts = (Timestamp) this.value;
return new Point2d(ts.doubleValue(), 0);
case DATE:
final Date dt = (Date) this.value;
return new Point2d(dt.getTime(), 0);
case POINT:
return new Point2d(((Point2D<?, ?>) this.value).getX(),
((Point2D<?, ?>) this.value).getY());
case POINT3D:
final Point3D<?, ?> pt3 = (Point3D<?, ?>) this.value;
return new Point2d(pt3.getX(), pt3.getY());
case STRING:
return parsePoint((String) this.value, false);
case OBJECT:
return getPointFromObject();
case BOOLEAN:
case IMAGE:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException | NumberFormatException exception) {
//
}
throw new InvalidAttributeTypeException();
}
private Point2D<?, ?> getPointFromObject() throws InvalidAttributeTypeException {
if (this.value instanceof Tuple3D<?>) {
final Tuple3D<?> t3 = (Tuple3D<?>) this.value;
return new Point2d(t3.getX(), t3.getY());
}
if (this.value instanceof Tuple2D<?>) {
final Tuple2D<?> t2 = (Tuple2D<?>) this.value;
return new Point2d(t2.getX(), t2.getY());
}
throw new InvalidAttributeTypeException();
}
@Override
public void setPoint(Point2D<?, ?> value) {
this.value = value;
this.type = AttributeType.POINT;
this.assigned = this.value != null;
}
@Override
public void setPoint(float x, float y) {
this.value = new Point2d(x, y);
this.type = AttributeType.POINT;
this.assigned = true;
}
@SuppressWarnings({"checkstyle:magicnumber", "checkstyle:cyclomaticcomplexity",
"checkstyle:booleanexpressioncomplexity"})
private static Color parseColor(String text, boolean isStrict) {
final String[] comp = text.split(";"); //$NON-NLS-1$
if (isStrict && comp.length != 3 && comp.length != 4) {
return null;
}
int red = 0;
int green = 0;
int blue = 0;
int alpha = 255;
if (comp.length > 0) {
red = Integer.parseInt(comp[0]);
}
if (comp.length > 1) {
green = Integer.parseInt(comp[1]);
}
if (comp.length > 2) {
blue = Integer.parseInt(comp[2]);
}
if (comp.length > 3) {
alpha = Integer.parseInt(comp[3]);
}
if ((red < 256) && (red >= 0) && (green < 256) && (green >= 0) && (blue < 256) && (blue >= 0)
&& (alpha < 256) && (alpha >= 0)) {
return VectorToolkit.color(red, green, blue, alpha);
}
return null;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity"})
public Color getColor() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case COLOR:
final Color col = (Color) this.value;
return VectorToolkit.color(col.getRed(), col.getGreen(), col.getBlue(), col.getAlpha());
case POINT:
final Point2D<?, ?> pt2 = (Point2D<?, ?>) this.value;
return VectorToolkit.color((float) pt2.getX(), (float) pt2.getY(), 0, 1);
case POINT3D:
final Point3D<?, ?> pt3 = (Point3D<?, ?>) this.value;
return VectorToolkit.color((float) pt3.getX(), (float) pt3.getY(), (float) pt3.getZ(), 1);
case STRING:
final Color color = parseColor((String) this.value, false);
if (color != null) {
return color;
}
break;
case INTEGER:
return VectorToolkit.color(((Long) this.value).intValue());
case TIMESTAMP:
return VectorToolkit.color(((Timestamp) this.value).intValue());
case REAL:
return VectorToolkit.color(((Double) this.value).intValue());
case DATE:
return VectorToolkit.color((int) ((Date) this.value).getTime());
case OBJECT:
return getColorFromObject();
case BOOLEAN:
case IMAGE:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException | NumberFormatException exception) {
//
}
throw new InvalidAttributeTypeException();
}
private Color getColorFromObject() throws InvalidAttributeTypeException {
if (this.value instanceof Color) {
return (Color) this.value;
}
if (this.value instanceof Number) {
return VectorToolkit.color(((Number) this.value).intValue());
}
if (this.value instanceof Date) {
return VectorToolkit.color((int) ((Date) this.value).getTime());
}
if (this.value instanceof Calendar) {
return VectorToolkit.color((int) ((Calendar) this.value).getTimeInMillis());
}
throw new InvalidAttributeTypeException();
}
@Override
public void setColor(Color color) {
this.value = color;
this.type = AttributeType.COLOR;
this.assigned = this.value != null;
}
@Override
public void setColor(float red, float green, float blue) {
this.value = VectorToolkit.color(red, green, blue, 1);
this.type = AttributeType.COLOR;
this.assigned = true;
}
@Override
public void setColor(float red, float green, float blue, float alpha) {
this.value = VectorToolkit.color(red, green, blue, alpha);
this.type = AttributeType.COLOR;
this.assigned = true;
}
@Override
@SuppressWarnings("checkstyle:magicnumber")
public void setColor(int red, int green, int blue) {
this.value = VectorToolkit.color(red, green, blue, 255);
this.type = AttributeType.COLOR;
this.assigned = true;
}
@Override
public void setColor(int red, int green, int blue, int alpha) {
this.value = VectorToolkit.color(red, green, blue, alpha);
this.type = AttributeType.COLOR;
this.assigned = true;
}
private static UUID parseUUID(String text) {
try {
final URI uri = new URI(text);
if (UUID_STR.equalsIgnoreCase(uri.getScheme())) {
return UUID.fromString(uri.getHost());
}
} catch (Throwable exception) {
//
}
try {
return UUID.fromString(text);
} catch (Throwable exception) {
//
}
return null;
}
private static UUID extractUUIDFromString(URI uri) {
try {
return UUID.fromString(uri.getHost());
} catch (AssertionError e) {
throw e;
} catch (Throwable exception) {
return null;
}
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity",
"checkstyle:npathcomplexity"})
public UUID getUUID() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case UUID:
final UUID id = (UUID) this.value;
return new UUID(id.getMostSignificantBits(), id.getLeastSignificantBits());
case URI:
final URI uri = (URI) this.value;
if (UUID_STR.equalsIgnoreCase(uri.getScheme())) {
return extractUUIDFromString(uri);
}
break;
case OBJECT:
return getUUIDFromObject();
case STRING:
case BOOLEAN:
case COLOR:
case DATE:
case IMAGE:
case INTEGER:
case POINT:
case POINT3D:
case POLYLINE:
case POLYLINE3D:
case REAL:
case TIMESTAMP:
case URL:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
break;
}
} catch (ClassCastException | NumberFormatException exception) {
//
}
if (this.value == null) {
return (UUID) AttributeType.UUID.getDefaultValue();
}
final String s = this.value.toString();
if (s == null || "".equals(s)) { //$NON-NLS-1$
return (UUID) AttributeType.UUID.getDefaultValue();
}
try {
return UUID.fromString(s);
} catch (AssertionError e) {
throw e;
} catch (Throwable exception) {
//
}
return UUID.nameUUIDFromBytes(s.getBytes());
}
private UUID getUUIDFromObject() throws InvalidAttributeTypeException {
if (this.value instanceof UUID) {
return (UUID) this.value;
}
if (this.value instanceof URI
&& UUID_STR.equalsIgnoreCase(((URI) this.value).getScheme())) {
return extractUUIDFromString((URI) this.value);
}
throw new InvalidAttributeTypeException();
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity",
"checkstyle:npathcomplexity"})
public URL getURL() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case URL:
return new URL(((URL) this.value).toExternalForm());
case URI:
return ((URI) this.value).toURL();
case STRING:
return new URL((String) this.value);
case OBJECT:
return getURLFromObject();
case INET_ADDRESS:
return new URL(DEFAULT_SCHEME.name(), ((InetAddress) this.value).getHostAddress(), ""); //$NON-NLS-1$
case UUID:
case BOOLEAN:
case COLOR:
case DATE:
case IMAGE:
case INTEGER:
case POINT:
case POINT3D:
case POLYLINE:
case POLYLINE3D:
case REAL:
case TIMESTAMP:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException | MalformedURLException exception) {
//
}
if (this.value == null) {
return (URL) AttributeType.URL.getDefaultValue();
}
final String s = this.value.toString();
if (s == null) {
return (URL) AttributeType.URL.getDefaultValue();
}
try {
return new URL(s);
} catch (MalformedURLException exception) {
throw new InvalidAttributeTypeException();
}
}
private URL getURLFromObject() throws MalformedURLException, InvalidAttributeTypeException {
if (this.value instanceof URL) {
return (URL) this.value;
}
if (this.value instanceof URI) {
return ((URI) this.value).toURL();
}
throw new InvalidAttributeTypeException();
}
private static URI parseURI(String text) {
try {
final URI uri = new URI(text);
if (uri.getScheme() != null && !uri.getScheme().isEmpty()) {
return uri;
}
} catch (Throwable exception) {
//
}
return null;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity",
"checkstyle:npathcomplexity"})
public URI getURI() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case URL:
return ((URL) this.value).toURI();
case URI:
return new URI(((URI) this.value).toASCIIString());
case STRING:
return new URI((String) this.value);
case UUID:
return new URI(UUID_STR + ":" + ((UUID) this.value).toString()); //$NON-NLS-1$
case OBJECT:
return getURIFromObject();
case INET_ADDRESS:
return new URI(DEFAULT_SCHEME.name(), ((InetAddress) this.value).getHostAddress(), ""); //$NON-NLS-1$
case BOOLEAN:
case COLOR:
case DATE:
case IMAGE:
case INTEGER:
case POINT:
case POINT3D:
case POLYLINE:
case POLYLINE3D:
case REAL:
case TIMESTAMP:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException | URISyntaxException exception) {
//
}
if (this.value == null) {
return (URI) AttributeType.URI.getDefaultValue();
}
final String s = this.value.toString();
if (s == null) {
return (URI) AttributeType.URI.getDefaultValue();
}
try {
return new URI(s);
} catch (URISyntaxException exception) {
throw new InvalidAttributeTypeException();
}
}
private URI getURIFromObject() throws URISyntaxException, InvalidAttributeTypeException {
if (this.value instanceof URI) {
return (URI) this.value;
}
if (this.value instanceof URL) {
return ((URL) this.value).toURI();
}
if (this.value instanceof UUID) {
return new URI(UUID_STR + ":" + ((UUID) this.value).toString()); //$NON-NLS-1$
}
throw new InvalidAttributeTypeException();
}
@Override
public void setUUID(UUID u) {
this.value = (u == null) ? AttributeType.UUID.getDefaultValue() : u;
this.type = AttributeType.UUID;
this.assigned = this.value != null;
}
/**
* Set the value of this metadata.
*
* @param id identifier.
*/
public void setUUID(String id) {
try {
this.value = (id != null) ? UUID.fromString(id) : null;
} catch (Throwable exception) {
assert id != null;
this.value = UUID.nameUUIDFromBytes(id.getBytes());
}
this.type = AttributeType.UUID;
this.assigned = this.value != null;
}
@Override
public void setURL(URL u) {
this.value = (u == null) ? AttributeType.URL.getDefaultValue() : u;
this.type = AttributeType.URL;
this.assigned = this.value != null;
}
/**
* Set the value of this metadata.
*
* @param url the url.
*/
public void setURL(String url) {
try {
this.value = (url != null) ? new URL(url) : null;
} catch (Throwable exception) {
this.value = null;
}
this.type = AttributeType.URL;
this.assigned = this.value != null;
}
@Override
public void setURI(URI u) {
this.value = (u == null) ? AttributeType.URI.getDefaultValue() : u;
this.type = AttributeType.URI;
this.assigned = this.value != null;
}
/**
* Set the value of this metadata.
*
* @param uri the uri.
*/
public void setURI(String uri) {
try {
this.value = (uri != null) ? new URI(uri) : null;
} catch (Throwable exception) {
this.value = null;
}
this.type = AttributeType.URI;
this.assigned = this.value != null;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity",
"checkstyle:npathcomplexity"})
public Image getImage() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssigned();
switch (this.type) {
case IMAGE:
assertAssignedAndNotNull();
return (Image) this.value;
case OBJECT:
if ((this.value == null) || (this.value instanceof Image)) {
return (Image) this.value;
}
break;
case BOOLEAN:
case COLOR:
case DATE:
case INTEGER:
case POINT:
case POINT3D:
case POLYLINE:
case POLYLINE3D:
case REAL:
case STRING:
case TIMESTAMP:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException exception) {
//
}
throw new InvalidAttributeTypeException();
}
@Override
public void setImage(Image image) {
this.value = image;
this.type = AttributeType.IMAGE;
this.assigned = true;
}
private static Point3D<?, ?>[] parsePolyline3D(String text, boolean isStrict) {
final String[] comp = text.split(";"); //$NON-NLS-1$
if (isStrict && (comp.length % 3) != 0) {
return null;
}
final int fullPoints = comp.length / 3;
final boolean addPt = fullPoints * 3 != comp.length;
final Point3D<?, ?>[] tab = new Point3D[addPt ? fullPoints + 1 : fullPoints];
for (int i = 2, j = 0; (i < comp.length) && (j < tab.length); i += 3, ++j) {
tab[j] = new Point3d(
Double.parseDouble(comp[i - 2]),
Double.parseDouble(comp[i - 1]),
Double.parseDouble(comp[i]));
}
if (addPt) {
final double x = Double.parseDouble(comp[fullPoints * 3]);
final int idx = fullPoints * 3 + 1;
final double y = idx < comp.length ? Double.parseDouble(comp[idx]) : 0;
tab[tab.length - 1] = new Point3d(x, y, 0);
}
return tab;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity",
"checkstyle:npathcomplexity"})
public Point3D<?, ?>[] getPolyline3D() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case POINT:
final Point2D<?, ?> pt2 = (Point2D<?, ?>) this.value;
return new Point3D[] {
new Point3d(pt2.getX(), pt2.getY(), 0),
};
case POINT3D:
return new Point3D[] {
((Point3D<?, ?>) this.value).clone(),
};
case POLYLINE:
return getPolyline3DFromPolyline();
case POLYLINE3D:
return (Point3D[]) this.value;
case STRING:
return parsePolyline3D((String) this.value, false);
case OBJECT:
return getPolyline3DFromObject();
case BOOLEAN:
case COLOR:
case DATE:
case IMAGE:
case INTEGER:
case REAL:
case TIMESTAMP:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException | NumberFormatException exception) {
//
}
throw new InvalidAttributeTypeException();
}
private Point3D<?, ?>[] getPolyline3DFromPolyline() {
final Point2D<?, ?>[] current = (Point2D<?, ?>[]) this.value;
final Point3D<?, ?>[] tab = new Point3D[current.length];
for (int i = 0; i < current.length; ++i) {
tab[i] = new Point3d(
current[i].getX(),
current[i].getY(),
0);
}
return tab;
}
private Point3D<?, ?>[] getPolyline3DFromObject() throws InvalidAttributeTypeException {
if (this.value instanceof Tuple2D<?>) {
final Tuple2D<?> t2 = (Tuple2D<?>) this.value;
return new Point3D[] {new Point3d(t2.getX(), t2.getY(), 0),
};
} else if (this.value instanceof Tuple3D<?>) {
final Tuple3D<?> t2 = (Tuple3D<?>) this.value;
return new Point3D[] {new Point3d(t2.getX(), t2.getY(), t2.getZ()), };
} else if (this.value.getClass().isArray()) {
final Class<?> elementType = this.value.getClass().getComponentType();
if (Point3D.class.equals(elementType)) {
return (Point3D[]) this.value;
}
final int size = Array.getLength(this.value);
if (Tuple3D.class.isAssignableFrom(elementType)) {
final Point3D<?, ?>[] pa3 = new Point3D[size];
for (int i = 0; i < pa3.length; ++i) {
final Tuple3D<?> t = (Tuple3D<?>) Array.get(this.value, i);
pa3[i] = new Point3d(t);
}
return pa3;
}
if (Tuple2D.class.isAssignableFrom(elementType)) {
final Point3D<?, ?>[] pa3 = new Point3D[size];
for (int i = 0; i < pa3.length; ++i) {
final Tuple2D<?> t = (Tuple2D<?>) Array.get(this.value, i);
pa3[i] = new Point3d(t.getX(), t.getY(), 0);
}
return pa3;
}
}
throw new InvalidAttributeTypeException();
}
@Override
public void setPolyline3D(Point3D<?, ?>... value) {
this.value = value;
this.type = AttributeType.POLYLINE3D;
this.assigned = this.value != null;
}
@Override
public void setPolyline3D(Collection<? extends Point3D<?, ?>> value) {
if (value == null) {
this.value = null;
} else {
final Point3D<?, ?>[] tab = new Point3D[value.size()];
value.toArray(tab);
this.value = tab;
}
this.type = AttributeType.POLYLINE3D;
this.assigned = this.value != null;
}
@Override
public void addToPolyline3D(Point3D<?, ?>... pts) {
final Point3D<?, ?>[] tab;
if (this.value instanceof Point3D[]) {
final int size = ((Point3D[]) this.value).length;
tab = new Point3D[size + pts.length];
System.arraycopy(this.value, 0, tab, 0, size);
System.arraycopy(pts, 0, tab, size, pts.length);
} else {
tab = pts;
}
this.value = tab;
this.assigned = this.value != null;
this.type = AttributeType.POLYLINE3D;
}
@Override
public void addToPolyline3D(Collection<? extends Point3D<?, ?>> pts) {
final Point3D<?, ?>[] tab;
if (this.value instanceof Point3D[]) {
final int size = ((Point3D[]) this.value).length;
tab = new Point3D[size + pts.size()];
System.arraycopy(this.value, 0, tab, 0, size);
System.arraycopy(pts.toArray(), 0, tab, size, pts.size());
} else {
tab = new Point3D[pts.size()];
pts.toArray(tab);
}
this.value = tab;
this.assigned = this.value != null;
this.type = AttributeType.POLYLINE3D;
}
private static Point2D<?, ?>[] parsePolyline(String text, boolean isStrict) {
final String[] comp = text.split(";"); //$NON-NLS-1$
if (isStrict && (comp.length % 2) != 0) {
return null;
}
final int fullPoints = comp.length / 2;
final boolean addPt = fullPoints * 2 != comp.length;
final Point2D<?, ?>[] tab = new Point2D[addPt ? fullPoints + 1 : fullPoints];
for (int i = 1, j = 0; (i < comp.length) && (j < fullPoints); i += 2, ++j) {
tab[j] = new Point2d(
Double.parseDouble(comp[i - 1]),
Double.parseDouble(comp[i]));
}
if (addPt) {
tab[tab.length - 1] = new Point2d(
Double.parseDouble(comp[comp.length - 1]),
0);
}
return tab;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity",
"checkstyle:npathcomplexity"})
public Point2D<?, ?>[] getPolyline() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case POINT:
return new Point2D[] {
new Point2d(((Point2D<?, ?>) this.value).getX(), ((Point2D<?, ?>) this.value).getY()),
};
case POINT3D:
final Point3D<?, ?> pt3 = (Point3D<?, ?>) this.value;
return new Point2D[] {
new Point2d(pt3.getX(), pt3.getY()),
};
case POLYLINE:
return (Point2D[]) this.value;
case POLYLINE3D:
return getPolylineFromPolyline3D();
case STRING:
return parsePolyline((String) this.value, false);
case OBJECT:
return getPoint2DFromPolyline();
case BOOLEAN:
case COLOR:
case DATE:
case IMAGE:
case INTEGER:
case REAL:
case TIMESTAMP:
case URI:
case URL:
case UUID:
case INET_ADDRESS:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException | NumberFormatException exception) {
//
}
throw new InvalidAttributeTypeException();
}
private Point2D<?, ?>[] getPolylineFromPolyline3D() {
final Point3D<?, ?>[] current = (Point3D[]) this.value;
final Point2D<?, ?>[] tab = new Point2D<?, ?>[current.length];
for (int i = 0; i < current.length; ++i) {
tab[i] = new Point2d(current[i].getX(), current[i].getY());
}
return tab;
}
private Point2D<?, ?>[] getPoint2DFromPolyline() {
if (this.value instanceof Tuple2D) {
return new Point2D[] {new Point2d(((Tuple2D<?>) this.value).getX(), ((Tuple2D<?>) this.value).getY()), };
} else if (this.value instanceof Tuple3D) {
final Tuple3D<?> t3 = (Tuple3D<?>) this.value;
return new Point2D[] {new Point2d(t3.getX(), t3.getY()),
};
} else if (this.value instanceof Point2D[]) {
return (Point2D[]) this.value;
} else if (this.value instanceof Tuple2D[]) {
final Tuple2D<?>[] ta2 = (Tuple2D[]) this.value;
final Point2D<?, ?>[] pa2 = new Point2D[ta2.length];
for (int i = 0; i < pa2.length; ++i) {
pa2[i] = new Point2d(ta2[i]);
}
} else if (this.value instanceof Tuple3D[]) {
final Tuple3D<?>[] ta3 = (Tuple3D[]) this.value;
final Point2D<?, ?>[] pa2 = new Point2D<?, ?>[ta3.length];
for (int i = 0; i < pa2.length; ++i) {
pa2[i] = new Point2d(ta3[i].getX(), ta3[i].getY());
}
}
return null;
}
@Override
public void setPolyline(Point2D<?, ?>... value) {
this.value = value;
this.type = AttributeType.POLYLINE;
this.assigned = this.value != null;
}
@Override
public void setPolyline(Collection<? extends Point2D<?, ?>> value) {
if (value == null) {
this.value = null;
} else {
final Point2D<?, ?>[] tab = new Point2D<?, ?>[value.size()];
value.toArray(tab);
this.value = tab;
}
this.value = value;
this.type = AttributeType.POLYLINE;
this.assigned = this.value != null;
}
@Override
public void addToPolyline(Point2D<?, ?>... pts) {
final Point2D<?, ?>[] tab;
if (this.value instanceof Point2D[]) {
final int size = ((Point2D<?, ?>[]) this.value).length;
tab = new Point2D[size + pts.length];
System.arraycopy(this.value, 0, tab, 0, size);
System.arraycopy(this.value, 0, tab, size, pts.length);
} else {
tab = pts;
}
this.value = tab;
this.assigned = this.value != null;
this.type = AttributeType.POLYLINE;
}
@Override
public void addToPolyline(Collection<? extends Point2D<?, ?>> pts) {
final Point2D<?, ?>[] tab;
if (this.value instanceof Point2D[]) {
final int size = ((Point2D<?, ?>[]) this.value).length;
tab = new Point2D[size + pts.size()];
System.arraycopy(this.value, 0, tab, 0, size);
System.arraycopy(this.value, 0, tab, size, pts.size());
} else {
tab = new Point2D[pts.size()];
pts.toArray(tab);
}
this.value = tab;
this.assigned = this.value != null;
this.type = AttributeType.POLYLINE;
}
private InetAddress extractInetAddress() {
try {
final InetAddress adr = InetAddress.getByName(this.value.toString());
if (adr != null) {
return adr;
}
} catch (Throwable exception) {
//
}
return null;
}
@Pure
@Override
@SuppressWarnings({"checkstyle:returncount", "checkstyle:cyclomaticcomplexity",
"checkstyle:npathcomplexity"})
public InetAddress getInetAddress() throws InvalidAttributeTypeException, AttributeNotInitializedException {
try {
assertAssignedAndNotNull();
switch (this.type) {
case INET_ADDRESS:
return (InetAddress) this.value;
case STRING:
return extractInetAddress();
case OBJECT:
return getInetAddressFromObject();
case URI:
final URI uri = (URI) this.value;
return InetAddress.getByName(uri.getHost());
case URL:
final URL url = (URL) this.value;
return InetAddress.getByName(url.getHost());
case COLOR:
case POINT:
case POINT3D:
case INTEGER:
case TIMESTAMP:
case REAL:
case DATE:
case BOOLEAN:
case IMAGE:
case POLYLINE:
case POLYLINE3D:
case UUID:
case ENUMERATION:
case TYPE:
default:
}
} catch (ClassCastException | NumberFormatException | UnknownHostException exception) {
//
}
throw new InvalidAttributeTypeException();
}
private InetAddress getInetAddressFromObject() throws InvalidAttributeTypeException {
if (this.value instanceof InetAddress) {
return (InetAddress) this.value;
}
if (this.value instanceof InetSocketAddress) {
return ((InetSocketAddress) this.value).getAddress();
}
if (this.value != null) {
return extractInetAddress();
}
throw new InvalidAttributeTypeException();
}
@Override
public void setInetAddress(InetAddress address) {
this.value = address;
this.type = AttributeType.INET_ADDRESS;
this.assigned = this.value != null;
}
/**
* Set the value of this metadata.
*
* @param address the address.
*/
public void setInetAddress(InetSocketAddress address) {
this.value = address.getAddress();
this.type = AttributeType.INET_ADDRESS;
this.assigned = this.value != null;
}
/**
* Set the value of this metadata.
*
* @param hostname the hostname
*/
public void setInetAddress(String hostname) {
this.type = AttributeType.INET_ADDRESS;
try {
this.value = InetAddress.getByName(hostname);
} catch (Throwable exception) {
this.value = null;
}
this.assigned = this.value != null;
}
@Pure
@Override
@SuppressWarnings("checkstyle:cyclomaticcomplexity")
public Enum<?> getEnumeration() throws InvalidAttributeTypeException, AttributeNotInitializedException {
if (this.value == null) {
return null;
}
try {
assertAssignedAndNotNull();
switch (this.type) {
case ENUMERATION:
return (Enum<?>) this.value;
case STRING:
return getEnumerationFromString();
case OBJECT:
if (this.value instanceof Enum<?>) {
return (Enum<?>) this.value;
}
break;
case REAL:
case INTEGER:
break;
case INET_ADDRESS:
case COLOR:
case POINT:
case POINT3D:
case TIMESTAMP:
case DATE:
case BOOLEAN:
case IMAGE:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case TYPE:
default:
}
} catch (Throwable exception) {
//
}
throw new InvalidAttributeTypeException();
}
@Pure
@Override
@SuppressWarnings("checkstyle:cyclomaticcomplexity")
public <T extends Enum<T>> T getEnumeration(Class<T> type) throws InvalidAttributeTypeException,
AttributeNotInitializedException {
if (this.value == null) {
return null;
}
try {
assertAssignedAndNotNull();
switch (this.type) {
case ENUMERATION:
return type.cast(this.value);
case STRING:
return getEnumerationFromString(type);
case OBJECT:
if (this.value instanceof Enum<?>) {
return type.cast(this.value);
}
break;
case REAL:
case INTEGER:
break;
case INET_ADDRESS:
case COLOR:
case POINT:
case POINT3D:
case TIMESTAMP:
case DATE:
case BOOLEAN:
case IMAGE:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
case TYPE:
default:
}
} catch (Throwable exception) {
//
}
throw new InvalidAttributeTypeException();
}
@Override
public void setEnumeration(Enum<?> enumConstant) {
this.value = enumConstant;
this.type = AttributeType.ENUMERATION;
this.assigned = this.value != null;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Enum<?> getEnumerationFromString() throws ClassNotFoundException, InvalidAttributeTypeException {
final int index = ((String) this.value).lastIndexOf('.');
if (index >= 0) {
final String classname = ((String) this.value).substring(0, index);
final String enumName = ((String) this.value).substring(index + 1);
final Class classType = Class.forName(classname);
if (Enum.class.isAssignableFrom(classType)) {
return Enum.valueOf(classType, enumName);
}
}
throw new InvalidAttributeTypeException();
}
private <T extends Enum<T>> T getEnumerationFromString(Class<T> type) throws Exception {
final int index = ((String) this.value).lastIndexOf('.');
if (index >= 0) {
final String classname = ((String) this.value).substring(0, index);
final String enumName = ((String) this.value).substring(index + 1);
final Class<?> classType = Class.forName(classname);
assert type.equals(classType);
return Enum.valueOf(type, enumName);
}
return null;
}
@Pure
@Override
@SuppressWarnings("checkstyle:cyclomaticcomplexity")
public Class<?> getJavaClass() throws InvalidAttributeTypeException, AttributeNotInitializedException {
assertAssignedAndNotNull();
try {
switch (this.type) {
case TYPE:
case OBJECT:
return (Class<?>) this.value;
case STRING:
return Class.forName((String) this.value);
case ENUMERATION:
case REAL:
case INTEGER:
case INET_ADDRESS:
case COLOR:
case POINT:
case POINT3D:
case TIMESTAMP:
case DATE:
case BOOLEAN:
case IMAGE:
case POLYLINE:
case POLYLINE3D:
case URI:
case URL:
case UUID:
default:
}
} catch (Throwable exception) {
//
}
throw new InvalidAttributeTypeException();
}
@Override
public void setJavaClass(Class<?> type) {
this.value = type;
this.type = AttributeType.TYPE;
this.assigned = this.value != null;
}
@Pure
@Override
public boolean isAssigned() {
return this.assigned;
}
@Override
public void uninitializeValue() {
this.value = null;
this.assigned = false;
}
@Override
public boolean flush() {
return true;
}
@Pure
@Override
public Comparator<? extends AttributeValue> valueComparator() {
return new AttributeValueComparator();
}
}