/*
* Copyright 2014 the original author or authors.
*
* Licensed 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.gradle.model;
import org.gradle.api.Incubating;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* A managed type is transparent to the model space, and enforces immutability at the appropriate times in the object's lifecycle.
* <p>
* Gradle generates implementations for managed types.
* As such, managed types are declared either as interfaces or abstract classes.
* The generated implementation integrates with the model space mechanisms, and manages mutability.
* <p>
* Managed types are mostly behaviour-less, as they are data.
* Instances of managed types should effectively be considered value objects.
*
* <h3>Properties</h3>
* <p>
* Managed types declare their structure as properties, via getter and setter methods.
* Getter and setter methods are expected to conform to the well-known Java Bean naming conventions.
* A read/write “name” property would be expressed via the following methods:
* <pre>
* void setName(String name);
* String getName();
* </pre>
* <p>
* A getter and setter must be declared for each property that is not of a managed type or of {@link ModelSet}.
* For properties of managed types or of {@link ModelSet} the getter is mandatory and the setter is optional.
* If no setter is provided the property is considered inherent and defaults to an "empty" instance of the type.
* In addition to the traditional getter method, properties of type {@code boolean} (but not {@code Boolean})
* also support a getter method which name starts with {@code is}, for example:
*
* <pre>
* void setEnabled(boolean enabled);
* boolean isEnabed();
* </pre>
*
* <h4>Supported property types</h4>
* <p>
* The following JDK types are allowed:
* <ul>
* <li>{@link String}</li>
* <li>{@link Boolean}</li>
* <li>{@link Character}</li>
* <li>{@link Byte}</li>
* <li>{@link Short}</li>
* <li>{@link Integer}</li>
* <li>{@link Long}</li>
* <li>{@link Float}</li>
* <li>{@link Double}</li>
* <li>{@link java.math.BigInteger}</li>
* <li>{@link java.math.BigDecimal}</li>
* <li>{@link java.io.File}</li>
* </ul>
* <p>
* All primitive types and {@link Enum} types are also allowed.
* <p>
* Properties that are themselves of a managed type are also supported.
* <p>
* Currently, the only collection types that are supported are {@link ModelSet} and {@link ModelMap}, as well as {@link java.util.Set} or {@link java.util.List}
* of {@link org.gradle.model.internal.manage.schema.extract.ScalarTypes scalar types}, where scalar types is either one of the supported immutable JDK types above or an enumeration.
* <p>
* Properties of any other type must have their getter annotated with {@link Unmanaged}.
* An unmanaged property is not transparent to the model infrastructure and is guaranteed to be immutable when realized.
*
* <h3>Named types</h3>
* <p>
* Managed types may implement/extend the {@link org.gradle.api.Named} interface.
* Any managed type implementing this interface will have its {@code name} attribute populated automatically
* based on the name of the corresponding node in the model graph.
* <p>
* The {@link ModelMap} type requires that its elements are {@link org.gradle.api.Named}.
*
* <h3>Inheritance</h3>
* <p>
* Managed types can be arranged into an inheritance hierarchy.
* Every type in the hierarchy must conform to the constraints of managed types.
*
* <h3>Calculated read-only properties</h3>
* <p>
* Managed types can contain getter methods that return calculated values, based on other properties.
* For example, a “name” property may return the concatenation of a “firstName” and “lastName” property.
* When using Java 8 or later, such properties can be implemented as interface default methods.
* Alternatively, the managed type can be implemented as an abstract class with the calculated property implemented as a non-abstract getter method.
* In both cases, the implementation of the calculated property getter may not call any setter method.
*
* <h3>Abstract classes</h3>
* <p>
* A managed type can be implemented as an abstract class.
* All property getters and setters must be declared {@code abstract} (with the exception of calculated read-only properties).
* The class cannot contain instance variables, constructors, or any methods that are not a getter or setter.
*
* <h3>Creating managed model elements</h3>
* <p>
* Please see {@link Model} for information on creating model elements of managed types.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Incubating
public @interface Managed {
}