001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2003-2023 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.feature;
019
020import java.lang.reflect.Method;    // For javadoc
021import org.opengis.annotation.UML;
022import org.opengis.annotation.Classifier;
023import org.opengis.annotation.Stereotype;
024import org.opengis.parameter.ParameterValueGroup;
025import org.opengis.parameter.ParameterDescriptorGroup;
026
027import static org.opengis.annotation.Obligation.*;
028import static org.opengis.annotation.Specification.ISO_19109;
029
030
031/**
032 * Describes the behaviour of a feature type as a function or a method.
033 * Operations can:
034 *
035 * <ul>
036 *   <li>Compute values from the attributes.</li>
037 *   <li>Perform actions that change the attribute values.</li>
038 * </ul>
039 *
040 * <div class="note"><b>Example:</b> a mutator operation may raise the height of a dam. This changes
041 * may affect other properties like the watercourse and the reservoir associated with the dam.</div>
042 *
043 * This {@code Operation} type is used for defining the required parameters and expected result.
044 *
045 * @author  Jody Garnett (Refractions Research, Inc.)
046 * @author  Martin Desruisseaux (Geomatys)
047 * @version 3.1
048 * @since   3.1
049 */
050@Classifier(Stereotype.METACLASS)
051@UML(identifier="Operation", specification=ISO_19109)
052public interface Operation extends PropertyType {
053    /**
054     * Returns a description of the input parameters.
055     *
056     * @return description of the input parameters.
057     */
058    @UML(identifier="signature", obligation=MANDATORY, specification=ISO_19109)
059    ParameterDescriptorGroup getParameters();
060
061    /**
062     * Returns the expected result type, or {@code null} if none.
063     *
064     * @return the type of the result, or {@code null} if none.
065     */
066    @UML(identifier="signature", obligation=MANDATORY, specification=ISO_19109)
067    IdentifiedType getResult();
068
069    /**
070     * Executes the operation on the specified feature with the specified parameters.
071     * The {@code parameters} argument should be an instance created like below, where
072     * the text in italic shall be replaced by operation-specific text:
073     *
074     * {@snippet lang="java" :
075     * ParameterValueGroup p = operation.getParameters().createValue();
076     * p.parameter("a parameter 1").setValue(aValue1);
077     * p.parameter("a parameter 2").setValue(aValue2);
078     * }
079     *
080     * The value returned by this method depends on the value returned by {@link #getResult()}:
081     * <ul>
082     *   <li>If {@code getResult()} returns {@code null},
083     *       then this method should return {@code null}.</li>
084     *   <li>If {@code getResult()} returns an instance of {@link AttributeType},
085     *       then this method shall return an instance of {@link Attribute}
086     *       and the {@code Attribute.getType() == getResult()} relation should hold.</li>
087     *   <li>If {@code getResult()} returns an instance of {@link FeatureAssociationRole},
088     *       then this method shall return an instance of {@link FeatureAssociation}
089     *       and the {@code FeatureAssociation.getRole() == getResult()} relation should hold.</li>
090     * </ul>
091     *
092     * <div class="note"><b>Analogy with Java reflection</b>:
093     * if we compare {@code Operation} to {@link Method} in the Java language, then this method is equivalent
094     * to {@link Method#invoke(Object, Object...)}. The {@code Feature} argument is equivalent to {@code this}
095     * in the Java language, and may be {@code null} if the operation does not need a feature instance
096     * (like static methods in the Java language).</div>
097     *
098     * <div class="note"><b>API note</b>:
099     * the method signature is compatible with {@code BiFunction<Feature, ParameterValueGroup, Property>} from
100     * the {@link java.util.function} package.</div>
101     *
102     * @param  feature    the feature on which to execute the operation.
103     *                    Can be {@code null} if the operation does not need feature instance.
104     * @param  parameters the parameters to use for executing the operation.
105     *                    Can be {@code null} if the operation does not take any parameters.
106     * @return the operation result, or {@code null} if this operation does not produce any result.
107     * @throws FeatureOperationException if the operation cannot complete.
108     */
109    Property apply(Feature feature, ParameterValueGroup parameters) throws FeatureOperationException;
110}