cc.recommenders.names.VmTypeName.java Source code

Java tutorial

Introduction

Here is the source code for cc.recommenders.names.VmTypeName.java

Source

/**
 * Copyright (c) 2010 Darmstadt University of Technology.
 * 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
 *
 * Contributors:
 *    Marcel Bruch - initial API and implementation.
 */
package cc.recommenders.names;

import static cc.recommenders.assertions.Checks.ensureIsFalse;
import static cc.recommenders.assertions.Checks.ensureIsNotNull;
import static cc.recommenders.assertions.Checks.ensureIsTrue;
import static cc.recommenders.assertions.Throws.throwIllegalArgumentException;
import static cc.recommenders.assertions.Throws.throwUnreachable;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.google.common.collect.MapMaker;

public class VmTypeName implements ITypeName {
    private static Map<String /* vmTypeName */, VmTypeName> index = new MapMaker().weakValues().makeMap();

    public static final VmTypeName OBJECT = VmTypeName.get("Ljava/lang/Object");

    public static final VmTypeName JavaLangNullPointerException = VmTypeName.get("Ljava/lang/NullPointerException");

    public static final VmTypeName JavaLangOutOfMemoryError = VmTypeName.get("Ljava/lang/OutOfMemoryError");

    public static final VmTypeName JavaLangString = VmTypeName.get("Ljava/lang/String");

    public static final VmTypeName JavaLangExceptionInInitializerError = VmTypeName
            .get("Ljava/lang/ExceptionInInitializerError");

    public static final VmTypeName STRING = VmTypeName.get("Ljava/lang/String");

    public static final VmTypeName NULL = get("Lnull");

    public static final VmTypeName BYTE = get("B");

    public static final VmTypeName BOOLEAN = get("Z");

    public static final VmTypeName CHAR = get("C");

    public static final VmTypeName DOUBLE = get("D");

    public static final VmTypeName FLOAT = get("F");

    public static final VmTypeName INT = get("I");

    public static final VmTypeName LONG = get("J");

    public static final VmTypeName SHORT = get("S");

    public static final VmTypeName VOID = get("V");

    public static VmTypeName get(String typeName) {
        typeName = removeGenerics(typeName);
        VmTypeName res = index.get(typeName);
        if (res == null) {
            res = new VmTypeName(typeName);
            index.put(typeName, res);
        }
        return res;
    }

    private static String removeGenerics(final String typeName) {
        return StringUtils.substringBefore(typeName, "<");
    }

    private String identifier;

    protected VmTypeName() {
        // no-one should instantiate this class. O
    }

    /**
     * @see #get(String)
     */
    protected VmTypeName(final String vmTypeName) {
        ensureIsNotNull(vmTypeName);
        ensureIsFalse(vmTypeName.length() == 0, "empty size for type name not permitted");
        if (vmTypeName.length() == 1) {
            switch (vmTypeName.charAt(0)) {
            case 'B':
            case 'C':
            case 'D':
            case 'F':
            case 'I':
            case 'J':
            case 'S':
            case 'V':
            case 'Z':
                break;
            default:
                throwUnreachable("Invalid type name: " + vmTypeName);
            }
        } else {
            switch (vmTypeName.charAt(0)) {
            case '[':
            case 'L':
                break;
            default:
                throwUnreachable("Invalid type name: " + vmTypeName);
            }
        }

        int off = 0;
        while (off < vmTypeName.length()) {
            final char c = vmTypeName.charAt(off);
            if (c == '[' || c == '/' || c == '-'/* as in 'package-info.class' */ || c == '<' || c == '>'
                    || Character.isJavaIdentifierPart(c)) {
                off++;
                continue;
            }
            throwIllegalArgumentException("Cannot parse '%s' as vm type name.", vmTypeName);
            break;
        }
        identifier = vmTypeName;
    }

    @Override
    public ITypeName getArrayBaseType() {
        ensureIsTrue(isArrayType(), "only array-types have a base type!");
        int start = 0;
        while (identifier.charAt(++start) == '[') {
            // start counter gets increased
        }
        return get(identifier.substring(start));
    }

    @Override
    public int getArrayDimensions() {
        int count = 0;
        int start = 0;
        while (identifier.charAt(start++) == '[') {
            count++;
        }
        return count;
    }

    @Override
    public String getClassName() {
        final int indexOf = identifier.lastIndexOf('/');
        if (indexOf < 0 && !isPrimitiveType()) {
            return identifier.substring(1);
        }
        final String classname = identifier.substring(indexOf + 1);
        return classname;
    }

    @Override
    public String getIdentifier() {
        return identifier;
    }

    @Override
    public IPackageName getPackage() {
        final int lastSlash = identifier.lastIndexOf('/');
        if (lastSlash == -1 || identifier.charAt(0) == '[') {
            return VmPackageName.DEFAULT_PACKAGE;
        }
        return VmPackageName.get(identifier.substring(1, lastSlash));
    }

    @Override
    public boolean isAnonymousType() {
        return identifier.matches(".*\\$\\d+");
    }

    @Override
    public boolean isArrayType() {
        return identifier.charAt(0) == '[';
    }

    @Override
    public boolean isDeclaredType() {
        return identifier.charAt(0) == 'L';
    }

    @Override
    public boolean isNestedType() {
        return identifier.contains("$");
    }

    @Override
    public boolean isPrimitiveType() {
        return !(isArrayType() || isDeclaredType());
    }

    @Override
    public boolean isVoid() {
        return this == VOID;
    }

    @Override
    public int compareTo(final ITypeName o) {
        return getIdentifier().compareTo(o.getIdentifier());
    }

    @Override
    public String toString() {
        return getIdentifier();
    }

    @Override
    public IMethodName getDeclaringMethod() {
        ensureIsTrue(isNestedType(), "only valid on nested types");
        final int lastPathSegmentSeparator = identifier.lastIndexOf('/');
        final String path = identifier.substring(0, lastPathSegmentSeparator);
        final int bracket = path.lastIndexOf('(');
        final int methodSeparator = path.lastIndexOf('/', bracket);
        final String newFQName = path.substring(0, methodSeparator) + "." + path.substring(methodSeparator + 1);
        return VmMethodName.get(newFQName);
    }

    @Override
    public ITypeName getDeclaringType() {
        ensureIsTrue(isNestedType(), "only valid on nested types");
        final int lastIndexOf = identifier.lastIndexOf('$');
        final String declaringTypeName = identifier.substring(0, lastIndexOf);
        return get(declaringTypeName);
    }
}