/* * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.mdsal.binding2.generator.util; import com.google.common.annotations.Beta; import com.google.common.base.CharMatcher; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.Nullable; import org.opendaylight.mdsal.binding2.model.api.BaseTypeWithRestrictions; import org.opendaylight.mdsal.binding2.model.api.ConcreteType; import org.opendaylight.mdsal.binding2.model.api.ParameterizedType; import org.opendaylight.mdsal.binding2.model.api.Restrictions; import org.opendaylight.mdsal.binding2.model.api.Type; import org.opendaylight.mdsal.binding2.model.api.WildcardType; import org.opendaylight.mdsal.binding2.spec.Augmentable; import org.opendaylight.mdsal.binding2.spec.Augmentation; import org.opendaylight.mdsal.binding2.spec.RpcCallback; import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint; import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint; import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint; import org.opendaylight.yangtools.yang.model.util.BaseConstraints; @Beta public final class Types { public static final ConcreteType BOOLEAN = typeForClass(Boolean.class); public static final ConcreteType RPC_CALLBACK = typeForClass(RpcCallback.class); public static final ConcreteType STRING = typeForClass(String.class); public static final ConcreteType VOID = typeForClass(Void.class); public static final ConcreteType BYTE_ARRAY = primitiveType("byte[]", null); public static final ConcreteType CHAR_ARRAY = primitiveType("char[]", null); private static final Splitter DOT_SPLITTER = Splitter.on('.'); private static final Type SET_TYPE = typeForClass(Set.class); private static final Type LIST_TYPE = typeForClass(List.class); private static final Type MAP_TYPE = typeForClass(Map.class); private static final CacheLoader, ConcreteType> TYPE_LOADER = new CacheLoader, ConcreteType>() { @Override public ConcreteType load(Class key) throws Exception { return new ConcreteTypeImpl(key.getPackage().getName(), key.getSimpleName(), null); } }; private static final LoadingCache, ConcreteType> TYPE_CACHE = CacheBuilder.newBuilder().weakKeys().build(TYPE_LOADER); private Types() { throw new UnsupportedOperationException("Utility class"); } /** * Creates the instance of type * {@link org.opendaylight.mdsal.binding2.model.api.ConcreteType * ConcreteType} which represents JAVA void type. * * @return ConcreteType instance which represents JAVA * void */ public static ConcreteType voidType() { return VOID; } /** * Creates the instance of type * {@link org.opendaylight.mdsal.binding2.model.api.ConcreteType * ConcreteType} which represents primitive JAVA type for which package * doesn't exist. * * @param primitiveType * string containing programmatic construction based on * primitive type (e.g byte[]) * @return ConcreteType instance which represents programmatic * construction with primitive JAVA type */ public static ConcreteType primitiveType(final String primitiveType, final Restrictions restrictions) { return new ConcreteTypeImpl("", primitiveType, restrictions); } /** * Returns an instance of {@link ConcreteType} describing the class * * @param cls * Class to describe * @return Description of class */ public static ConcreteType typeForClass(final Class cls) { return TYPE_CACHE.getUnchecked(cls); } public static ConcreteType typeForClass(final Class cls, final Restrictions restrictions) { if (restrictions != null) { if (restrictions instanceof DefaultRestrictions) { return new ConcreteTypeImpl(cls.getPackage().getName(), cls.getSimpleName(), restrictions); } else { return new BaseTypeWithRestrictionsImpl(cls.getPackage().getName(), cls.getSimpleName(), restrictions); } } else { return typeForClass(cls); } } /** * Returns an instance of {@link ParameterizedType} describing the typed * {@link Map}<K,V> * * @param keyType * Key Type * @param valueType * Value Type * @return Description of generic type instance */ public static ParameterizedType mapTypeFor(final Type keyType, final Type valueType) { return parameterizedTypeFor(MAP_TYPE, keyType, valueType); } /** * Returns an instance of {@link ParameterizedType} describing the typed * {@link Set}<V> with concrete type of value. * * @param valueType * Value Type * @return Description of generic type instance of Set */ public static ParameterizedType setTypeFor(final Type valueType) { return parameterizedTypeFor(SET_TYPE, valueType); } /** * Returns an instance of {@link ParameterizedType} describing the typed * {@link List}<V> with concrete type of value. * * @param valueType * Value Type * @return Description of type instance of List */ public static ParameterizedType listTypeFor(final Type valueType) { return parameterizedTypeFor(LIST_TYPE, valueType); } /** * Creates instance of type * {@link org.opendaylight.mdsal.binding2.model.api.ParameterizedType * ParameterizedType} * * @param type * JAVA Type for raw type * @param parameters * JAVA Types for actual parameter types * @return ParametrizedType reprezentation of type * and its parameters parameters */ public static ParameterizedType parameterizedTypeFor(final Type type, final Type... parameters) { return new ParameterizedTypeImpl(type, parameters); } /** * Creates instance of type * {@link org.opendaylight.mdsal.binding2.model.api.WildcardType * WildcardType} * * @param packageName * string with the package name * @param typeName * string with the type name * @return WildcardType representation of * packageName and typeName */ public static WildcardType wildcardTypeFor(final String packageName, final String typeName) { return new WildcardTypeImpl(packageName, typeName); } /** * Creates instance of * {@link org.opendaylight.mdsal.binding2.model.api.ParameterizedType * ParameterizedType} where raw type is * {@link org.opendaylight.mdsal.binding2.spec.Augmentable} and actual * parameter is valueType. * * @param valueType * JAVA Type with actual parameter * @return ParametrizedType representation of raw type * Augmentable with actual parameter * valueType */ public static ParameterizedType augmentableTypeFor(final Type valueType) { final Type augmentable = typeForClass(Augmentable.class); return parameterizedTypeFor(augmentable, valueType); } /** * Creates instance of * {@link org.opendaylight.mdsal.binding2.model.api.ParameterizedType * ParameterizedType} where raw type is * {@link org.opendaylight.mdsal.binding2.spec.Augmentation} and actual * parameter is valueType. * * @param valueType * JAVA Type with actual parameter * @return ParametrizedType reprezentation of raw type * Augmentation with actual parameter * valueType */ public static ParameterizedType augmentationTypeFor(final Type valueType) { final Type augmentation = typeForClass(Augmentation.class); return parameterizedTypeFor(augmentation, valueType); } public static @Nullable String getOuterClassName(final Type valueType) { final String pkgName = valueType.getPackageName(); if(CharMatcher.JAVA_UPPER_CASE.indexIn(pkgName) >= 0) { // It is inner class. return Iterables.getLast(DOT_SPLITTER.split(pkgName)); } return null; } /** * * Represents concrete JAVA type. * */ private static final class ConcreteTypeImpl extends AbstractBaseType implements ConcreteType { private final Restrictions restrictions; /** * Creates instance of this class with package pkName and * with the type name name. * * @param pkName * string with package name * @param name * string with the name of the type */ private ConcreteTypeImpl(final String pkName, final String name, final Restrictions restrictions) { super(pkName, name); this.restrictions = restrictions; } @Override public Restrictions getRestrictions() { return restrictions; } } /** * * Represents concrete JAVA type with changed restriction values. * */ private static final class BaseTypeWithRestrictionsImpl extends AbstractBaseType implements BaseTypeWithRestrictions { private final Restrictions restrictions; /** * Creates instance of this class with package pkName and * with the type name name. * * @param pkName * string with package name * @param name * string with the name of the type */ private BaseTypeWithRestrictionsImpl(final String pkName, final String name, final Restrictions restrictions) { super(pkName, name); this.restrictions = Preconditions.checkNotNull(restrictions); } @Override public Restrictions getRestrictions() { return restrictions; } } /** * * Represents parametrized JAVA type. * */ private static class ParameterizedTypeImpl extends AbstractBaseType implements ParameterizedType { /** * Array of JAVA actual type parameters. */ private final Type[] actualTypes; /** * JAVA raw type (like List, Set, Map...) */ private final Type rawType; @Override public Type[] getActualTypeArguments() { return actualTypes; } @Override public Type getRawType() { return rawType; } /** * Creates instance of this class with concrete rawType and array of * actual parameters. * * @param rawType * JAVA Type for raw type * @param actTypes * array of actual parameters */ public ParameterizedTypeImpl(final Type rawType, final Type[] actTypes) { super(rawType.getPackageName(), rawType.getName()); this.rawType = rawType; this.actualTypes = actTypes.clone(); } } /** * * Represents JAVA bounded wildcard type. * */ private static class WildcardTypeImpl extends AbstractBaseType implements WildcardType { /** * Creates instance of this class with concrete package and type name. * * @param packageName * string with the package name * @param typeName * string with the name of type */ public WildcardTypeImpl(final String packageName, final String typeName) { super(packageName, typeName); } } public static DefaultRestrictions getDefaultRestrictions(final T min, final T max) { return new DefaultRestrictions<>(min, max); } private static final class DefaultRestrictions implements Restrictions { private final T min; private final T max; private final List rangeConstraints; private DefaultRestrictions(final T min, final T max) { this.min = Preconditions.checkNotNull(min); this.max = Preconditions.checkNotNull(max); this.rangeConstraints = Collections.singletonList(BaseConstraints.newRangeConstraint(min, max, Optional .absent(), Optional.absent())); } @Override public boolean isEmpty() { return false; } @Override public List getRangeConstraints() { return rangeConstraints; } @Override public List getPatternConstraints() { return ImmutableList.of(); } @Override public List getLengthConstraints() { return ImmutableList.of(); } } }