/**
*
* Copyright (c) 2006-2017, Speedment, Inc. All Rights Reserved.
*
* 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 com.speedment.common.codegen.model;
import com.speedment.common.codegen.constant.DefaultType;
import com.speedment.common.codegen.internal.model.GenericImpl;
import com.speedment.common.codegen.model.trait.HasCopy;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Optional;
/**
* A model that represents the generic part of a type declaration in code. A
* type can have multiple generics.
*
* @author Emil Forslund
* @since 2.0
*/
public interface Generic extends HasCopy<Generic> {
/**
* Represents the bound type of this generic. If the generic is bound using
* the <code>extends</code> keyword it means that the lower bound is a
* descendant of the upper bound. If the <code>super</code> keyword is used
* it means that the lower bound is an ancestor of the upper bound. Both
* bound types also accept identical types.
*/
enum BoundType {
EXTENDS, SUPER
}
/**
* Sets the lower bound of this generic.
* <p>
* In the following example, <code>T</code> is the lower bound:
* <pre>
* T extends List<String>
* </pre>
* <p>
* If the lower bound is anonymous, the special type
* {@link DefaultType#WILDCARD} can be used.
*
* @param lowerBound the new lower bound
* @return a reference to this model
*/
Generic setLowerBound(String lowerBound);
/**
* Returns the lower bound of this generic if it exists.
* <p>
* In the following example, <code>T</code> is the lower bound:
* <pre>
* T extends List<String>
* </pre>
* <p>
* If the lower bound is anonymous, the special type
* {@link DefaultType#WILDCARD} can be used.
*
* @return the lower bound if such exists
*/
Optional<String> getLowerBound();
/**
* Adds an upper bound to this generic.
* <p>
* In the following example, <code>List<String></code> and
* <code>Serializable</code> are upper bounds:
* <pre>
* T extends List<String>&Serializable
* </pre>
*
* @param upperBound the new upper bound
* @return a reference to this model
*/
default Generic add(Type upperBound) {
getUpperBounds().add(upperBound);
return this;
}
/**
* Returns a modifiable list of all upper bounds to this generic.
* <p>
* In the following example, <code>List<String></code> and
* <code>Serializable</code> are upper bounds:
* <pre>
* T extends List<String>&Serializable
* </pre>
*
* @return the list of upper bounds
*/
List<Type> getUpperBounds();
/**
* Sets the bound type of this generic. If the generic is bound using the
* <code>extends</code> keyword it means that the lower bound is a
* descendant of the upper bound. If the <code>super</code> keyword is used
* it means that the lower bound is an ancestor of the upper bound. Both
* bound types also accept identical types.
* <p>
* Valid input:
* <ul>
* <li>{@link BoundType#EXTENDS}
* <li>{@link BoundType#SUPER}
* </ul>
*
* @param type the new bound type
* @return a reference to this model
*/
Generic setBoundType(BoundType type);
/**
* Returns the current bound type of this generic. Note that the bound type
* is irrelevant when there are no upper bounds!
*
* @return the bound type
*/
BoundType getBoundType();
/**
* Parses a {@link Type} from the lower bound of this generic. This can be
* used to reference the generic variable from other contexts.
*
* @return a {@link Type} representing this generic variable
*/
Type asType();
/**
* Creates a new instance implementing this interface by using the default
* implementation.
*
* @return the new instance
*/
static Generic of() {
return new GenericImpl();
}
/**
* Creates a new instance implementing this interface by using the default
* implementation.
*
* @param lowerBound the lower bound, example: {@code "T"}
* @return the new instance
*/
static Generic of(String lowerBound) {
return of().setLowerBound(lowerBound);
}
/**
* Creates a new instance implementing this interface by using the default
* implementation.
*
* @param upperBound the upper bound, example: {@code "String"}
* @return the new instance
*/
static Generic of(Type upperBound) {
return of().add(upperBound);
}
}