package io.lumify.core.model.properties.types; import com.google.common.base.Function; import com.google.common.collect.Iterables; import org.securegraph.*; import org.securegraph.mutation.ElementMutation; import org.securegraph.mutation.ExistingElementMutation; import java.util.Collections; import java.util.Map; /** * A LumifyProperty provides convenience methods for converting standard * property values to and from their raw types to the types required to * store them in a SecureGraph instance. * * @param <TRaw> the raw value type for this property * @param <TGraph> the value type presented to SecureGraph for this property */ public abstract class LumifyProperty<TRaw, TGraph> { /** * The property propertyName. */ private final String propertyName; /** * The raw conversion function. */ private final Function<Object, TRaw> rawConverter; /** * Create a new LumifyProperty with the given propertyName. * * @param propertyName the property propertyName */ protected LumifyProperty(final String propertyName) { this.propertyName = propertyName; this.rawConverter = new RawConverter(); } /** * Convert the raw value to an appropriate value for storage * in SecureGraph. * * @param value the raw value * @return the SecureGraph value type representing the input value */ public abstract TGraph wrap(final TRaw value); /** * Convert the SecureGraph value to its original raw type. * * @param value the SecureGraph value; may or may not be of type TGraph * @return the raw value represented by the input SecureGraph value * @throws ClassCastException if the provided value cannot be unwrapped */ public abstract TRaw unwrap(final Object value); /** * Get the property propertyName for this property. * * @return the property propertyName */ public final String getPropertyName() { return propertyName; } /** * Add a mutation to set this property to the provided value. * * @param mutation the element mutation * @param value the new property value * @param visibility the property visibility */ public final void setProperty(final ElementMutation<?> mutation, final TRaw value, final Visibility visibility) { mutation.setProperty(propertyName, wrap(value), visibility); } /** * Add a mutation to set this property to the provided value. * * @param mutation the element mutation * @param value the new property value * @param metadata the property metadata * @param visibility the property visibility */ public final void setProperty(final ElementMutation<?> mutation, final TRaw value, final Metadata metadata, final Visibility visibility) { mutation.setProperty(propertyName, wrap(value), metadata, visibility); } /** * Set this property on the provided element. * * @param element the element * @param value the new property value * @param visibility the property visibility */ public final void setProperty(final Element element, final TRaw value, final Visibility visibility, Authorizations authorizations) { element.setProperty(propertyName, wrap(value), visibility, authorizations); } /** * Set this property on the provided element. * * @param element the element * @param value the new property value * @param metadata the property metadata * @param visibility the property visibility */ public final void setProperty(final Element element, final TRaw value, final Metadata metadata, final Visibility visibility, Authorizations authorizations) { element.setProperty(propertyName, wrap(value), metadata, visibility, authorizations); } /** * Add a mutation to add a new value to this property. * * @param mutation the element mutation * @param multiKey the multi-valued property key * @param value the new property value * @param visibility the property visibility */ public final void addPropertyValue(final ElementMutation<?> mutation, final String multiKey, final TRaw value, final Visibility visibility) { mutation.addPropertyValue(multiKey, propertyName, wrap(value), visibility); } public final void addPropertyValue(final Element element, final String multiKey, final TRaw value, final Visibility visibility, Authorizations authorizations) { element.addPropertyValue(multiKey, propertyName, wrap(value), visibility, authorizations); } public final void addPropertyValue(final Element element, final String multiKey, final TRaw value, final Metadata metadata, final Visibility visibility, Authorizations authorizations) { element.addPropertyValue(multiKey, propertyName, wrap(value), metadata, visibility, authorizations); } /** * Add a mutation to add a new value to this property * * @param mutation the element mutation * @param multiKey the multi-valued property key * @param value the new property value * @param metadata the property metadata * @param visibility the property visibility */ public final void addPropertyValue(final ElementMutation<?> mutation, final String multiKey, final TRaw value, final Metadata metadata, final Visibility visibility) { mutation.addPropertyValue(multiKey, propertyName, wrap(value), metadata, visibility); } /** * Get the value of this property from the provided Element. * * @param element the element * @return the value of this property on the given Element or null if it is not configured */ public final TRaw getPropertyValue(final Element element) { Object value = element != null ? element.getPropertyValue(propertyName) : null; return value != null ? rawConverter.apply(value) : null; } public final TRaw getPropertyValue(final Element element, String propertyKey) { Object value = element != null ? element.getPropertyValue(propertyKey, propertyName) : null; return value != null ? rawConverter.apply(value) : null; } public final TRaw getPropertyValue(Property property) { Object value = property.getValue(); return value != null ? rawConverter.apply(value) : null; } /** * Get all values of this property from the provided Element. * * @param element the element * @return an Iterable over the values of this property on the given Element */ @SuppressWarnings("unchecked") public final Iterable<TRaw> getPropertyValues(final Element element) { Iterable<Object> values = element != null ? element.getPropertyValues(propertyName) : null; return values != null ? Iterables.transform(values, rawConverter) : Collections.EMPTY_LIST; } public boolean hasProperty(Element element, String propertyKey) { return element.getProperty(propertyKey, getPropertyName()) != null; } public TRaw getMetadataValue(Metadata metadata) { return unwrap(metadata.getValue(propertyName)); } public TRaw getMetadataValueOrDefault(Metadata metadata, TRaw defaultValue) { Object value = metadata.getValue(propertyName); if (value == null) { return defaultValue; } return unwrap(value); } public TRaw getMetadataValue(Map<String, Object> metadata) { return unwrap(metadata.get(propertyName)); } public TRaw getMetadataValue(Metadata metadata, TRaw defaultValue) { if (metadata.getEntry(propertyName) == null) { return defaultValue; } return unwrap(metadata.getValue(propertyName)); } public void setMetadata(Metadata metadata, TRaw value, Visibility visibility) { metadata.add(propertyName, wrap(value), visibility); } public void setMetadata(ExistingElementMutation m, Property property, TRaw value, Visibility visibility) { m.setPropertyMetadata(property, propertyName, wrap(value), visibility); } public Property getProperty(Element element) { return element.getProperty(getPropertyName()); } public Iterable<Property> getProperties(Element element) { return element.getProperties(getPropertyName()); } public void removeProperty(Element element, String key, Authorizations authorizations) { element.removeProperty(key, getPropertyName(), authorizations); } public void removeProperty(Element element, Authorizations authorizations) { element.removeProperty(getPropertyName(), authorizations); } public void removeProperty(ElementMutation m, final Visibility visibility) { m.removeProperty(getPropertyName(), visibility); } public void removeProperty(ElementMutation m, String key, final Visibility visibility) { m.removeProperty(key, getPropertyName(), visibility); } public void removeMetadata(Metadata metadata) { metadata.remove(getPropertyName()); } public void removeMetadata(Metadata metadata, final Visibility visibility) { metadata.remove(getPropertyName(), visibility); } public void alterVisibility(ExistingElementMutation<?> elementMutation, Visibility newVisibility) { elementMutation.alterPropertyVisibility(getPropertyName(), newVisibility); } public void alterVisibility(ExistingElementMutation<?> elementMutation, String propertyKey, Visibility newVisibility) { elementMutation.alterPropertyVisibility(propertyKey, getPropertyName(), newVisibility); } /** * Function that converts the values returned by the Vertex.getProperty() * methods to the configured TRaw type. */ private class RawConverter implements Function<Object, TRaw> { @Override @SuppressWarnings("unchecked") public TRaw apply(final Object input) { return unwrap(input); } } }