edu.northwestern.bioinformatics.studycalendar.osgi.felixcm.OsgiConfigurationProperty.java Source code

Java tutorial

Introduction

Here is the source code for edu.northwestern.bioinformatics.studycalendar.osgi.felixcm.OsgiConfigurationProperty.java

Source

/*L
 * Copyright Northwestern University.
 *
 * Distributed under the OSI-approved BSD 3-Clause License.
 * See http://ncip.github.io/psc/LICENSE.txt for details.
 */

package edu.northwestern.bioinformatics.studycalendar.osgi.felixcm;

import edu.northwestern.bioinformatics.studycalendar.StudyCalendarError;
import edu.northwestern.bioinformatics.studycalendar.StudyCalendarSystemException;
import gov.nih.nci.cabig.ctms.domain.CodedEnum;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.IndexColumn;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.Proxy;

import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.persistence.Version;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * A representation of a single KV pair for an OSGi configuration.
 *
 * @author Rhett Sutphin
 * @see edu.northwestern.bioinformatics.studycalendar.osgi.felixcm.internal.PscFelixPersistenceManager
 */
@SuppressWarnings({ "RawUseOfParameterizedType" })
@Entity
@Proxy(lazy = false)
@Table(name = "osgi_cm_properties")
@GenericGenerator(name = "id-generator", strategy = "native", parameters = {
        @Parameter(name = "sequence", value = "seq_osgi_cm_properties_id") })
public class OsgiConfigurationProperty {
    private Integer id, version;
    private String servicePid;
    private String name;
    private CollectionType collectionType;
    private Type type;
    private List<String> rawValues;

    public OsgiConfigurationProperty() {
        rawValues = new ArrayList<String>();
    }

    ////// LOGIC

    @Transient
    public Object getValue() {
        switch (getCollectionType()) {
        case SINGLE:
            return getSingleValue();
        case VECTOR:
            return getVectorValue();
        case ARRAY:
            return getArrayValue();
        }
        throw new UnsupportedOperationException("Unsupported collection type: " + getCollectionType());
    }

    @Transient
    private Object getSingleValue() {
        return getType().convert(getRawValues().get(0));
    }

    @Transient
    private Vector<?> getVectorValue() {
        Vector<Object> result = new Vector<Object>();
        for (String rawValue : getRawValues()) {
            result.add(getType().convert(rawValue));
        }
        return result;
    }

    @Transient
    private Object getArrayValue() {
        Object result = getType().createArray(getRawValues().size());
        for (int i = 0; i < getRawValues().size(); i++) {
            String rawValue = getRawValues().get(i);
            Array.set(result, i, getType().convert(rawValue));
        }
        return result;
    }

    public void setValue(Object value) {
        if (value.getClass().isArray()) {
            setArrayValue(value);
        } else if (value instanceof List) {
            setVectorValue((List) value);
        } else {
            setSingleValue(value.toString(), Type.fromJavaClass(value.getClass()));
        }
    }

    private void setArrayValue(Object value) {
        setCollectionType(CollectionType.ARRAY);
        setType(Type.fromJavaClass(value.getClass().getComponentType()));
        getRawValues().clear();
        int len = Array.getLength(value);
        for (int i = 0; i < len; i++) {
            getRawValues().add(Array.get(value, i).toString());
        }
    }

    private void setVectorValue(List list) {
        setCollectionType(CollectionType.VECTOR);
        if (list.isEmpty()) {
            setType(Type.STRING); // default type
        } else {
            setType(Type.fromJavaClass(list.get(0).getClass()));
            getRawValues().clear();
            for (Object o : list) {
                getRawValues().add(o.toString());
            }
        }
    }

    private void setSingleValue(String serializedValue, Type type) {
        setCollectionType(CollectionType.SINGLE);
        setType(type);
        getRawValues().clear();
        getRawValues().add(serializedValue);
    }

    ////// BOUND PROPERTIES

    @Id
    @GeneratedValue(generator = "id-generator")
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Version
    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }

    public String getServicePid() {
        return servicePid;
    }

    public void setServicePid(String servicePid) {
        this.servicePid = servicePid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "collection_kind")
    @Enumerated(EnumType.STRING)
    public CollectionType getCollectionType() {
        return collectionType;
    }

    public void setCollectionType(CollectionType collectionType) {
        this.collectionType = collectionType;
    }

    @Column(name = "kind")
    @org.hibernate.annotations.Type(type = "edu.northwestern.bioinformatics.studycalendar.domain.tools.hibernate.StringCodedEnumType", parameters = {
            @Parameter(name = "enumClass", value = "edu.northwestern.bioinformatics.studycalendar.osgi.felixcm.OsgiConfigurationProperty$Type") })
    public Type getType() {
        return type;
    }

    public void setType(Type type) {
        this.type = type;
    }

    @ElementCollection(fetch = FetchType.EAGER)
    @Column(name = "value")
    @JoinTable(name = "osgi_cm_property_values", joinColumns = @JoinColumn(name = "property_id", nullable = false))
    @IndexColumn(name = "list_index", nullable = false)
    @Cascade({ CascadeType.ALL, CascadeType.DELETE_ORPHAN })
    public List<String> getRawValues() {
        return rawValues;
    }

    public void setRawValues(List<String> rawValues) {
        this.rawValues = rawValues;
    }

    public static OsgiConfigurationProperty create(String pid, String name, Object value) {
        OsgiConfigurationProperty property = new OsgiConfigurationProperty();
        property.setServicePid(pid);
        property.setName(name);
        property.setValue(value);
        return property;
    }

    ////// ENUMERATIONS

    public enum CollectionType {
        SINGLE, ARRAY, VECTOR
    }

    public enum Type implements CodedEnum<String> {
        STRING(String.class) {
            @Override
            public Object convert(String serialized) {
                return serialized;
            }
        },
        INTEGER(Integer.class), LONG(Long.class), FLOAT(Float.class), DOUBLE(Double.class), BYTE(Byte.class), SHORT(
                Short.class), CHARACTER(Character.class), BOOLEAN(Boolean.class),

        PRIMITIVE_LONG(Long.TYPE, Long.class), PRIMITIVE_INT(Integer.TYPE, Integer.class), PRIMITIVE_SHORT(
                Short.TYPE, Short.class), PRIMITIVE_CHAR(Character.TYPE, Character.class), PRIMITIVE_BYTE(Byte.TYPE,
                        Byte.class), PRIMITIVE_DOUBLE(Double.TYPE, Double.class), PRIMITIVE_FLOAT(Float.TYPE,
                                Float.class), PRIMITIVE_BOOLEAN(Boolean.TYPE, Boolean.class);

        private Class<?> javaClass, boxClass;

        private Type(Class<?> javaClass) {
            this(javaClass, javaClass);
        }

        private Type(Class<?> javaClass, Class<?> boxClass) {
            this.javaClass = javaClass;
            this.boxClass = boxClass;
        }

        public Class<?> javaClass() {
            return javaClass;
        }

        public static Type fromJavaClass(Class<?> aClass) {
            for (Type type : values()) {
                if (type.javaClass().equals(aClass)) {
                    return type;
                }
            }
            return null;
        }

        public String typeName() {
            if (javaClass().isPrimitive()) {
                return name().replace("PRIMITIVE_", "").toLowerCase();
            } else {
                StringBuilder sb = new StringBuilder(name().toLowerCase());
                sb.setCharAt(0, name().charAt(0));
                return sb.toString();
            }
        }

        public static Type fromTypeName(String typeName) {
            try {
                if (Character.isLowerCase(typeName.charAt(0))) {
                    return valueOf("PRIMITIVE_" + typeName.toUpperCase());
                } else {
                    return valueOf(typeName.toUpperCase());
                }
            } catch (IllegalArgumentException iae) {
                return null;
            }
        }

        public Object createArray(int length) {
            return Array.newInstance(javaClass(), length);
        }

        public Object convert(String serialized) {
            if (boxClass.equals(Character.class)) {
                return serialized.charAt(0);
            }

            try {
                Constructor converter = boxClass.getConstructor(String.class);
                return converter.newInstance(serialized);
            } catch (NoSuchMethodException e) {
                throw new StudyCalendarError("Missing required constructor on " + boxClass.getName());
            } catch (InvocationTargetException e) {
                throw new StudyCalendarSystemException("Converting '%s' using type %s failed", e, serialized,
                        this.name());
            } catch (IllegalAccessException e) {
                throw new StudyCalendarSystemException("Converting '%s' using type %s failed", e, serialized,
                        this.name());
            } catch (InstantiationException e) {
                throw new StudyCalendarSystemException("Converting '%s' using type %s failed", e, serialized,
                        this.name());
            }
        }

        public static Type getByCode(String code) {
            return fromTypeName(code);
        }

        public String getCode() {
            return typeName();
        }

        public String getDisplayName() {
            return typeName();
        }
    }
}