msi.gaml.types.ParametricType.java Source code

Java tutorial

Introduction

Here is the source code for msi.gaml.types.ParametricType.java

Source

/*******************************************************************************************************
 *
 * msi.gaml.types.ParametricType.java, in plugin msi.gama.core, is part of the source code of the GAMA modeling and
 * simulation platform (v. 1.8)
 * 
 * (c) 2007-2018 UMI 209 UMMISCO IRD/SU & Partners
 *
 * Visit https://github.com/gama-platform/gama for license information and contacts.
 * 
 ********************************************************************************************************/
package msi.gaml.types;

import static com.google.common.cache.CacheBuilder.newBuilder;
import static java.util.concurrent.TimeUnit.MINUTES;

import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.google.common.cache.Cache;

import msi.gama.precompiler.ISymbolKind;
import msi.gama.runtime.IScope;
import msi.gama.runtime.exceptions.GamaRuntimeException;
import msi.gama.util.IContainer;
import msi.gaml.descriptions.IDescription;
import msi.gaml.descriptions.OperatorProto;
import msi.gaml.descriptions.SpeciesDescription;
import msi.gaml.expressions.IExpression;
import ummisco.gama.dev.utils.DEBUG;

/**
 * Class ParametricType. A class that allows to build composed types with a content type and a key type
 *
 * @author drogoul
 * @since 19 janv. 2014
 *
 */
public class ParametricType implements IContainerType<IContainer<?, ?>> {

    static {
        DEBUG.OFF();
    }

    static Cache<Integer, ParametricType> CACHE2 = newBuilder().expireAfterAccess(1, MINUTES).weakValues()
            ./* recordStats(). */ build();
    static boolean USE_CACHE = true;

    public static ParametricType createParametricType(final IContainerType<IContainer<?, ?>> t, final IType<?> kt,
            final IType<?> ct) {
        if (USE_CACHE) {
            final Integer key = t.hashCode() + ct.hashCode() * 100 + kt.hashCode() * 10000;
            ParametricType p = CACHE2.getIfPresent(key);
            if (p == null) {
                p = new ParametricType(t, kt, ct);
                CACHE2.put(key, p);
                // DEBUG.OUT(CACHE2.stats().toString() + " Size: " + CACHE2.size());
            }
            return p;
        }
        return new ParametricType(t, kt, ct);
    }

    private final IContainerType<IContainer<?, ?>> type;
    private final IType<?> contentsType;
    private final IType<?> keyType;

    protected ParametricType(final IContainerType<IContainer<?, ?>> t, final IType<?> kt, final IType<?> ct) {
        type = t;
        contentsType = ct;
        keyType = kt;
    }

    @Override
    public boolean isCompoundType() {
        return true;
    }

    @Override
    public boolean equals(final Object other) {
        if (other instanceof ParametricType) {
            return type.equals(((ParametricType) other).getGamlType())
                    && keyType.equals(((ParametricType) other).getKeyType())
                    && contentsType.equals(((ParametricType) other).getContentType());
        }
        return false;
    }

    @Override
    public int hashCode() {
        return type.hashCode() + contentsType.hashCode() * 100 + keyType.hashCode() * 10000;
    }

    @Override
    public String getDefiningPlugin() {
        return type.getDefiningPlugin();
    }

    /**
     * Method getType()
     * 
     * @see msi.gama.common.interfaces.ITyped#getGamlType()
     */
    @Override
    public IContainerType<IContainer<?, ?>> getGamlType() {
        return type;
    }

    /**
     * Method cast()
     * 
     * @see msi.gaml.types.IType#cast(msi.gama.runtime.IScope, java.lang.Object, java.lang.Object, msi.gaml.types.IType,
     *      msi.gaml.types.IType)
     */
    @Override
    public IContainer<?, ?> cast(final IScope scope, final Object obj, final Object param, final IType<?> kt,
            final IType<?> ct, final boolean copy) throws GamaRuntimeException {
        return type.cast(scope, obj, param, keyType, contentsType, copy);
    }

    /**
     * Method id()
     * 
     * @see msi.gaml.types.IType#id()
     */
    @Override
    public int id() {
        return type.id();
    }

    /**
     * Method toClass()
     * 
     * @see msi.gaml.types.IType#toClass()
     */
    @Override
    public Class<? extends IContainer<?, ?>> toClass() {
        return type.toClass();
    }

    /**
     * Method getDefault()
     * 
     * @see msi.gaml.types.IType#getDefault()
     */
    @Override
    public IContainer<?, ?> getDefault() {
        return type.getDefault();
    }

    /**
     * Method getVarKind()
     * 
     * @see msi.gaml.types.IType#getVarKind()
     */
    @Override
    public int getVarKind() {
        return ISymbolKind.Variable.CONTAINER;
    }

    /**
     * Method getGetter()
     * 
     * @see msi.gaml.types.IType#getGetter(java.lang.String)
     */
    @Override
    public OperatorProto getGetter(final String name) {
        return type.getGetter(name);
    }

    /**
     * Method getFieldDescriptions()
     * 
     * @see msi.gaml.types.IType#getFieldDescriptions(msi.gaml.descriptions.ModelDescription)
     */
    // @Override
    // public Map getFieldDescriptions(final ModelDescription model) {
    // return type.getFieldDescriptions(model);
    // }

    /**
     * Method isSpeciesType()
     * 
     * @see msi.gaml.types.IType#isSpeciesType()
     */
    @Override
    public boolean isAgentType() {
        // Verify this
        return type.isAgentType();
    }

    /**
     * Method isSkillType()
     * 
     * @see msi.gaml.types.IType#isSkillType()
     */
    @Override
    public boolean isSkillType() {
        return false;
    }

    /**
     * Method defaultContentType()
     * 
     * @see msi.gaml.types.IType#defaultContentType()
     */
    @Override
    public IType<?> getContentType() {
        return contentsType;
    }

    /**
     * Method defaultKeyType()
     * 
     * @see msi.gaml.types.IType#defaultKeyType()
     */
    @Override
    public IType<?> getKeyType() {
        return keyType;
    }

    /**
     * Method getSpeciesName()
     * 
     * @see msi.gaml.types.IType#getSpeciesName()
     */
    @Override
    public String getSpeciesName() {
        return type.getSpeciesName();
    }

    /**
     * Method getSpecies()
     * 
     * @see msi.gaml.types.IType#getSpecies()
     */
    @Override
    public SpeciesDescription getSpecies() {
        final SpeciesDescription result = type.getSpecies();
        // if (result != null)
        return result;
        // return contentsType.getSpecies();
    }

    @Override
    public SpeciesDescription getDenotedSpecies() {
        final SpeciesDescription result = type.getSpecies();
        if (result != null) {
            return result;
        }
        return contentsType.getSpecies();
    }

    /**
     * Method isAssignableFrom()
     * 
     * @see msi.gaml.types.IType#isAssignableFrom(msi.gaml.types.IType)
     */
    @Override
    public boolean isAssignableFrom(final IType<?> l) {
        return type.isAssignableFrom(l.getGamlType()) && contentsType.isAssignableFrom(l.getContentType())
                && keyType.isAssignableFrom(l.getKeyType());
    }

    /**
     * Method isTranslatableInto()
     * 
     * @see msi.gaml.types.IType#isTranslatableInto(msi.gaml.types.IType)
     */
    @Override
    public boolean isTranslatableInto(final IType<?> l) {
        return type.isTranslatableInto(l.getGamlType()) && contentsType.isTranslatableInto(l.getContentType())
                && keyType.isTranslatableInto(l.getKeyType());
    }

    @Override
    public boolean isParametricFormOf(final IType<?> l) {
        return !l.isParametricType() && type.equals(l);
    }

    @Override
    public boolean isParametricType() {
        return true;
    }

    /**
     * Method setParent()
     * 
     * @see msi.gaml.types.IType#setParent(msi.gaml.types.IType)
     */
    @Override
    public void setParent(final IType<? super IContainer<?, ?>> p) {
    }

    /**
     * Method getParent()
     * 
     * @see msi.gaml.types.IType#getParent()
     */
    @Override
    public IType<?> getParent() {
        return type;
    }

    /**
     * Method coerce()
     * 
     * @see msi.gaml.types.IType#coerce(msi.gaml.types.IType, msi.gaml.descriptions.IDescription)
     */
    @Override
    public IType<?> coerce(final IType<?> expr, final IDescription context) {
        return null;
    }

    /**
     * Method distanceTo()
     * 
     * @see msi.gaml.types.IType#distanceTo(msi.gaml.types.IType)
     */
    @Override
    public int distanceTo(final IType<?> t) {
        return t.getGamlType().distanceTo(type) + t.getContentType().distanceTo(contentsType)
                + t.getKeyType().distanceTo(keyType);
    }

    /**
     * Method setFieldGetters()
     * 
     * @see msi.gaml.types.IType#setFieldGetters(java.util.Map)
     */
    @Override
    public void setFieldGetters(final Map<String, OperatorProto> map) {
    }

    /**
     * Method canBeTypeOf()
     * 
     * @see msi.gaml.types.IType#canBeTypeOf(msi.gama.runtime.IScope, java.lang.Object)
     */
    @Override
    public boolean canBeTypeOf(final IScope s, final Object c) {
        return type.canBeTypeOf(s, c);
    }

    /**
     * Method init()
     * 
     * @see msi.gaml.types.IType#init(int, int, java.lang.String, java.lang.Class[])
     */
    @Override
    public void init(final int varKind, final int id, final String name, final Class<IContainer<?, ?>> clazz) {
    }

    /**
     * Method isContainer()
     * 
     * @see msi.gaml.types.IType#isContainer()
     */
    @Override
    public boolean isContainer() {
        return true; // ???
    }

    /**
     * Method isFixedLength()
     * 
     * @see msi.gaml.types.IType#isFixedLength()
     */
    @Override
    public boolean isFixedLength() {
        return type.isFixedLength();
    }

    /**
     * Method findCommonSupertypeWith()
     * 
     * @see msi.gaml.types.IType#findCommonSupertypeWith(msi.gaml.types.IType)
     */
    @SuppressWarnings("unchecked")
    @Override
    public IType<? super IContainer<?, ?>> findCommonSupertypeWith(final IType<?> iType) {
        if (iType instanceof ParametricType) {
            final IType<?> pType = iType;
            final IType<?> cType = type.findCommonSupertypeWith(pType.getGamlType());
            if (cType.isContainer()) {
                final IType<?> kt = keyType.findCommonSupertypeWith(pType.getKeyType());
                final IType<?> ct = contentsType.findCommonSupertypeWith(pType.getContentType());
                return (IType<? super IContainer<?, ?>>) GamaType.from(cType, kt, ct);
            } else {
                return (IType<? super IContainer<?, ?>>) cType;
            }
        } else if (iType.isContainer()) {
            final IType<?> cType = type.findCommonSupertypeWith(iType);
            return (IType<? super IContainer<?, ?>>) cType;
            // dont we need to use the key and contents type here ?
        } else {
            return type.findCommonSupertypeWith(iType);
        }
    }

    /**
     * Method isParented()
     * 
     * @see msi.gaml.types.IType#isParented()
     */
    @Override
    public boolean isParented() {
        return true;
        // return type != null; // ??
    }

    @Override
    public boolean isDrawable() {
        return type.isDrawable();
    }

    /**
     * Method setSupport()
     * 
     * @see msi.gaml.types.IType#setSupport(java.lang.Class)
     */
    @Override
    public void setSupport(final Class<IContainer<?, ?>> clazz) {
    }

    @Override
    public IContainer<?, ?> cast(final IScope scope, final Object obj, final Object param, final boolean copy)
            throws GamaRuntimeException {
        return cast(scope, obj, param, keyType, contentsType, copy);
    }

    @Override
    public String toString() {
        if (type.id() == IType.LIST || type.id() == IType.MATRIX
                || type.id() == IType.CONTAINER && keyType == Types.NO_TYPE) {
            return type.toString() + "<" + contentsType.toString() + ">";
        }
        if (type.id() == IType.SPECIES) {
            return type.toString() + "<" + contentsType.toString() + ">";
        }
        return type.toString() + "<" + keyType.toString() + ", " + contentsType.toString() + ">";
    }

    @Override
    public String asPattern() {
        final boolean vowel = StringUtils.startsWithAny(type.getName(), vowels);
        return "${" + (vowel ? "an_" : "a_") + serialize(true) + "}";
    }

    @Override
    public String serialize(final boolean includingBuiltIn) {
        if (type.id() == IType.LIST || type.id() == IType.MATRIX
                || type.id() == IType.CONTAINER && keyType == Types.NO_TYPE) {
            return type.toString() + "<" + contentsType.toString() + ">";
        }
        if (type.id() == IType.SPECIES) {
            return type.toString() + "<" + contentsType.toString() + ">";
        }
        return type.toString() + "<" + keyType.serialize(includingBuiltIn) + ", "
                + contentsType.serialize(includingBuiltIn) + ">";
    }

    @Override
    public IContainerType<?> typeIfCasting(final IExpression exp) {
        if (contentsType == Types.NO_TYPE || keyType == Types.NO_TYPE) {
            final IType<?> genericCast = type.typeIfCasting(exp);
            final IType<?> ct = contentsType == Types.NO_TYPE ? genericCast.getContentType() : contentsType;
            final IType<?> kt = keyType == Types.NO_TYPE ? genericCast.getKeyType() : keyType;
            return createParametricType(type, kt, ct);
        }
        return this;
    }

    /**
     * Method getTitle()
     * 
     * @see msi.gama.common.interfaces.IGamlDescription#getTitle()
     */
    @Override
    public String getTitle() {
        return toString().replace('<', '[').replace('>', ']');
    }

    /**
     * Method getDocumentation()
     * 
     * @see msi.gama.common.interfaces.IGamlDescription#getDocumentation()
     */
    @Override
    public String getDocumentation() {
        return getTitle();
    }

    /**
     * Method getName()
     * 
     * @see msi.gama.common.interfaces.IGamlDescription#getName()
     */
    @Override
    public String getName() {
        return toString();
    }

    @Override
    public void setName(final String name) {
        // Nothing
    }

    @Override
    public boolean canCastToConst() {
        return type.canCastToConst() && contentsType.canCastToConst() && keyType.canCastToConst();
    }

    @Override
    public IContainerType<?> of(final IType<?>... subs) {
        if (subs.length == 0) {
            return this;
        }
        IType<?> kt = subs.length == 1 ? getKeyType() : subs[0];
        IType<?> ct = subs.length == 1 ? subs[0] : subs[1];
        if (ct == Types.NO_TYPE) {
            if (kt == Types.NO_TYPE) {
                return this;
            }
            ct = getContentType();
        }
        if (kt == Types.NO_TYPE) {
            kt = getKeyType();
        }
        return createParametricType(this, kt, ct);

    }

    /**
     * Method setDefiningPlugin()
     * 
     * @see msi.gaml.types.IType#setDefiningPlugin(java.lang.String)
     */
    @Override
    public void setDefiningPlugin(final String plugin) {
    }

    // @Override
    // public void collectMetaInformation(final GamlProperties meta) {
    // type.collectMetaInformation(meta);
    // contentsType.collectMetaInformation(meta);
    // keyType.collectMetaInformation(meta);
    // }

    @Override
    public boolean isNumber() {
        return false;
    }

    @Override
    public IType<?> getWrappedType() {
        return Types.NO_TYPE;
    }

    /*
     * (non-Javadoc)
     *
     * @see msi.gaml.types.IType#getFieldGetters()
     */
    @Override
    public Map<String, OperatorProto> getFieldGetters() {
        return type.getFieldGetters();
    }

}