/* * 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 { }