/*
* Copyright (c) 2017 OBiBa. All rights reserved.
*
* This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.obiba.magma.type;
import java.io.IOException;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.List;
import javax.annotation.Nullable;
import javax.validation.constraints.NotNull;
import org.obiba.magma.MagmaEngine;
import org.obiba.magma.Value;
import org.obiba.magma.ValueLoaderFactory;
import org.obiba.magma.ValueSequence;
import com.google.common.collect.Lists;
public class BinaryType extends AbstractValueType {
private static final long serialVersionUID = -5271259966499174607L;
@SuppressWarnings("StaticNonFinalField")
private static WeakReference<BinaryType> instance;
private BinaryType() {
}
@edu.umd.cs.findbugs.annotations.SuppressWarnings("NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE")
@SuppressWarnings("ConstantConditions")
@NotNull
public static BinaryType get() {
if(instance == null || instance.get() == null) {
instance = MagmaEngine.get().registerInstance(new BinaryType());
}
return instance.get();
}
@NotNull
@Override
public String getName() {
return "binary";
}
@Override
public Class<?> getJavaClass() {
return byte[].class;
}
@Override
public boolean acceptsJavaClass(@NotNull Class<?> clazz) {
return byte[].class.isAssignableFrom(clazz);
}
@Override
public boolean isDateTime() {
return false;
}
@Override
public boolean isNumeric() {
return false;
}
@Override
public boolean isBinary() {
return true;
}
@Override
protected String toString(Object object) {
return Base64.encodeBytes((byte[]) object);
}
@NotNull
@Override
public Value valueOf(@Nullable String string) {
if(string == null) {
return nullValue();
}
try {
return Factory.newValue(this, Base64.decode(string, Base64.DONT_GUNZIP));
} catch(IOException e) {
throw new IllegalArgumentException("Invalid Base64 encoding. Cannot construct binary Value instance.", e);
}
}
@NotNull
@Override
public Value valueOf(@Nullable Object object) {
// input type is expected to be byte[]
if(object == null) {
return nullValue();
}
Class<?> type = object.getClass();
if(byte[].class.equals(type)) {
return Factory.newValue(this, (Serializable) object);
}
if(String.class.isAssignableFrom(type)) {
return valueOf((String) object);
}
if(object instanceof Value) {
return convert((Value)object);
}
throw new IllegalArgumentException("Cannot construct " + getClass().getSimpleName() + " from type " + type + ".");
}
public ValueSequence sequenceOfReferences(ValueLoaderFactory factory, String string) {
Value refValues = TextType.get().sequenceOf(string);
return sequenceOfReferences(factory, refValues);
}
public ValueSequence sequenceOfReferences(ValueLoaderFactory factory, Value refValues) {
List<Value> values = Lists.newArrayList();
int occurrence = 0;
for(Value refValue : refValues.asSequence().getValues()) {
if(refValue.isNull()) {
values.add(get().nullValue());
} else {
values.add(valueOf(factory.create(refValue, occurrence)));
}
occurrence++;
}
return get().sequenceOf(values);
}
public Value valueOfReference(ValueLoaderFactory factory, String string) {
return valueOfReference(factory, TextType.get().valueOf(string));
}
public Value valueOfReference(ValueLoaderFactory factory, Value refValue) {
return valueOf(factory.create(refValue, null));
}
@Override
public int compare(Value o1, Value o2) {
if(o1 == null) throw new NullPointerException();
if(o2 == null) throw new NullPointerException();
if(!o1.getValueType().equals(this)) throw new ClassCastException();
if(!o2.getValueType().equals(this)) throw new ClassCastException();
// All byte[] are considered equal when sorting.
return 0;
}
}