/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.apache.tinkerpop.gremlin.structure; import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyProperty; import java.util.NoSuchElementException; import java.util.function.Consumer; import java.util.function.Supplier; /** * A {@link Property} denotes a key/value pair associated with an {@link Edge}. A property is much like a Java8 * {@link java.util.Optional} in that a property can be not present (i.e. empty). The key of a property is always a * String and the value of a property is an arbitrary Java object. Each underlying graph engine will typically have * constraints on what Java objects are allowed to be used as values. * * @author Marko A. Rodriguez (http://markorodriguez.com) * @author Stephen Mallette (http://stephen.genoprime.com) */ public interface Property<V> { /** * The key of the property. * * @return The property key */ public String key(); /** * The value of the property. * * @return The property value * @throws NoSuchElementException thrown if the property is empty */ public V value() throws NoSuchElementException; /** * Whether the property is empty or not. * * @return True if the property exists, else false */ public boolean isPresent(); /** * If the property is present, the consume the value as specified by the {@link Consumer}. * * @param consumer The consumer to process the existing value. */ public default void ifPresent(final Consumer<? super V> consumer) { if (this.isPresent()) consumer.accept(this.value()); } /** * If the value is present, return the value, else return the provided value. * * @param otherValue The value to return if the property is not present * @return A value */ public default V orElse(final V otherValue) { return this.isPresent() ? this.value() : otherValue; } /** * If the value is present, return the value, else generate a value given the {@link Supplier}. * * @param valueSupplier The supplier to use to generate a value if the property is not present * @return A value */ public default V orElseGet(final Supplier<? extends V> valueSupplier) { return this.isPresent() ? this.value() : valueSupplier.get(); } /** * If the value is present, return the value, else throw the exception generated by the {@link Supplier}. * * @param exceptionSupplier The supplier to generate an exception if the property is not present * @param <E> The exception type * @return A value * @throws E if the property is not present, the exception is thrown */ public default <E extends Throwable> V orElseThrow(final Supplier<? extends E> exceptionSupplier) throws E { if (this.isPresent()) return this.value(); else throw exceptionSupplier.get(); } /** * Get the element that this property is associated with. * * @return The element associated with this property (i.e. {@link Vertex}, {@link Edge}, or {@link VertexProperty}). */ public Element element(); /** * Remove the property from the associated element. */ public void remove(); /** * Create an empty property that is not present. * * @param <V> The value class of the empty property * @return A property that is not present */ public static <V> Property<V> empty() { return EmptyProperty.instance(); } /** * Common exceptions to use with a property. */ public static class Exceptions { private Exceptions() { } public static IllegalArgumentException propertyKeyCanNotBeEmpty() { return new IllegalArgumentException("Property key can not be the empty string"); } public static IllegalArgumentException propertyKeyCanNotBeNull() { return new IllegalArgumentException("Property key can not be null"); } public static IllegalArgumentException propertyValueCanNotBeNull() { return new IllegalArgumentException("Property value can not be null"); } public static IllegalArgumentException propertyKeyCanNotBeAHiddenKey(final String key) { return new IllegalArgumentException("Property key can not be a hidden key: " + key); } public static IllegalStateException propertyDoesNotExist() { return new IllegalStateException("The property does not exist as it has no key, value, or associated element"); } public static IllegalStateException propertyDoesNotExist(final Element element, final String key) { return new IllegalStateException("The property does not exist as the key has no associated value for the provided element: " + element + ":" + key); } public static IllegalArgumentException dataTypeOfPropertyValueNotSupported(final Object val) { return dataTypeOfPropertyValueNotSupported(val, null); } public static IllegalArgumentException dataTypeOfPropertyValueNotSupported(final Object val, final Exception rootCause) { return new IllegalArgumentException(String.format("Property value [%s] is of type %s is not supported", val, val.getClass()), rootCause); } public static IllegalStateException propertyRemovalNotSupported() { return new IllegalStateException("Property removal is not supported"); } } }