All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jace.metaclass.ClassMetaClass Maven / Gradle / Ivy

There is a newer version: 1.2.22
Show newest version
package org.jace.metaclass;

import com.google.common.collect.Lists;
import org.jace.util.CKeyword;
import java.util.ArrayList;
import java.util.List;

/**
 * Represents meta-data for class types.
 *
 * This helps prevent any sort of naming clashes caused by using other tools
 * that work with standard java class libraries.
 *
 * @author Toby Reyelts
 * @author Gili Tzabari
 */
public class ClassMetaClass implements MetaClass
{
	private final static String newLine = System.getProperty("line.separator");
	private String mName;
	private String mNewName;
	private ClassPackage mPackage;

	/**
	 * Creates a new ClassMetaClass.
	 *
	 * @param name the class name
	 * @param aPackage the class package
	 * @see MetaClassFactory#getMetaClass(org.jace.metaclass.TypeName)
	 */
	ClassMetaClass(String name, ClassPackage aPackage)
	{
		mName = name;
		mNewName = CKeyword.adjust(mName);
		mPackage = aPackage;
	}

	@Override
	public String getSimpleName()
	{
		return mNewName;
	}

	/**
	 * Returns the C++ file name that should be used for this MetaClass.
	 *
	 * For example, for java.lang.String, this would return String. For
	 * java.util.Map.EntrySet, this would return Map_EntrySet.
	 *
	 * @return the file name that should be used for this MetaClass
	 */
	public String getFileName()
	{
		return mName.replace('$', '_');
	}

	/**
	 * Returns the name of the class, without the keyword mangling that occurs to make it compatible with C++.
	 *
	 * @return the name of the class, without the keyword mangling that occurs to make it compatible with C++
	 */
	public String getTrueName()
	{
		return mName;
	}

	@Override
	public String getFullyQualifiedName(String separator)
	{
		return getPackage().toName(separator, true) + getSimpleName();
	}

	public String getFullyQualifiedTrueName(String separator)
	{
		return getPackage().toName(separator, true) + getTrueName();
	}

	/**
	 * Returns the ClassPackage for this MetaClass.
	 *
	 * @return the ClassPackage for this MetaClass
	 */
	@Override
	public ClassPackage getPackage()
	{
		return mPackage;
	}

	private String getGuardName()
	{
		StringBuilder guardName = new StringBuilder(mPackage.toName("_", true).toUpperCase());
		guardName.append(mNewName.toUpperCase()).append("_H");

		return guardName.toString();
	}

	@Override
	public String beginGuard()
	{
		String guardName = getGuardName();
		StringBuilder result = new StringBuilder("#ifndef ".length() + guardName.length() * 2 + "#define ".
			length());

		result.append("#ifndef ");
		result.append(guardName);
		result.append(newLine);
		result.append("#define ");
		result.append(guardName);
		return result.toString();
	}

	@Override
	public String endGuard()
	{
		StringBuilder guardName = new StringBuilder(mPackage.toName("_", true).toUpperCase());
		guardName.append(mNewName.toUpperCase()).append("_H");

		return "#endif // #ifndef " + guardName.toString();
	}

	@Override
	public String include()
	{
		StringBuilder include = new StringBuilder("#include \"");

		String packageName = mPackage.toName("/", true);
		String includeName = mName.replace('$', '_');
		include.append(packageName).append(includeName).append(".h\"");

		return include.toString();
	}

	@Override
	public String using()
	{
		StringBuilder using = new StringBuilder("using ");
		String packageName = mPackage.toName("::", true);
		using.append(packageName).append(mNewName).append(";");

		return using.toString();
	}

	@Override
	public String forwardDeclare()
	{
		StringBuilder forwardDeclaration = new StringBuilder("BEGIN_NAMESPACE_");
		String length = String.valueOf(mPackage.getPath().size());

		StringBuilder namespace = new StringBuilder("(");
		namespace.append(mPackage.toName(", ", false));
		namespace.append(")");

		forwardDeclaration.append(length).append(namespace.toString()).append(newLine);
		forwardDeclaration.append("class ").append(getSimpleName()).append(";").append(newLine);
		forwardDeclaration.append("END_NAMESPACE_").append(length).append(namespace);

		return forwardDeclaration.toString();
	}

	@Override
	public ClassMetaClass proxy()
	{
		if (mPackage.isProxied())
			throw new IllegalStateException("MetaClass is already a proxy: " + getFullyQualifiedName("."));
		List jaceProxy = JaceConstants.getProxyPackage().getComponents();
		List packagePath = mPackage.getPath();
		List newPackage = Lists.newArrayListWithCapacity(jaceProxy.size() + packagePath.size());
		newPackage.addAll(jaceProxy);
		newPackage.addAll(packagePath);
		return new ClassMetaClass(mName, new ClassPackage(newPackage));
	}

	@Override
	public ClassMetaClass unProxy()
	{
		if (!mPackage.isProxied())
			throw new IllegalStateException("MetaClass is not a proxy: " + getFullyQualifiedName("."));
		List path = mPackage.getPath();
		List newPackage = path.subList(JaceConstants.getProxyPackage().getComponents().size(), path.
			size());
		assert (newPackage.size() != 1 || !newPackage.get(0).equals("types"));
		return new ClassMetaClass(mName, new ClassPackage(newPackage));
	}

	public ClassMetaClass toPeer()
	{
		List result = new ArrayList(JaceConstants.getPeerPackage().getComponents());
		for (String path: mPackage.getPath())
			result.add(path);
		return new ClassMetaClass(mName, new ClassPackage(result));
	}

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

	@Override
	public String getJniType()
	{
		String name = getFullyQualifiedTrueName(".");
		if (name.equals("java.lang.Class"))
			return "jclass";
		if (name.equals("java.lang.String"))
			return "jstring";
		if (name.equals("java.lang.Throwable"))
			return "jthrowable";
		return "jobject";
	}

	/**
	 * Compares this MetaClass to another.
	 *
	 * Two MetaClasses are equal if they have the same name and belong to the same package.
	 * @param o the object to compare to
	 */
	@Override
	public boolean equals(Object o)
	{
		if (!(o instanceof ClassMetaClass))
			return false;
		ClassMetaClass other = (ClassMetaClass) o;
		return other.getSimpleName().equals(getSimpleName()) && other.getPackage().equals(getPackage());
	}

	@Override
	public int hashCode()
	{
		// Can't do a better hashCode than this, because we want to have proxied and deproxied classes compare equal
		return mName.hashCode();
	}

	@Override
	public String toString()
	{
		return getFullyQualifiedTrueName(".");
	}

	/**
	 * Tests ClassMetaClass.
	 *
	 * @param args the command-line argument
	 */
	@SuppressWarnings("UseOfSystemOutOrSystemErr")
	public static void main(String[] args)
	{
		ClassMetaClass metaClass = (ClassMetaClass) MetaClassFactory.getMetaClass(TypeNameFactory.
			fromIdentifier(args[0])).
			proxy();
		MetaClass metaClass2 = MetaClassFactory.getMetaClass(TypeNameFactory.fromIdentifier(args[0])).
			proxy();
		MetaClass metaClass3 = MetaClassFactory.getMetaClass(TypeNameFactory.fromIdentifier("["
																																												+ args[0])).
			proxy();
		MetaClass metaClass4 = MetaClassFactory.getMetaClass(TypeNameFactory.fromIdentifier("[["
																																												+ args[0])).
			proxy();

		System.out.println(metaClass.equals(metaClass2));
		System.out.println(metaClass.equals(metaClass3));
		System.out.println(metaClass3.equals(metaClass));
		System.out.println(metaClass.equals(metaClass4));
		System.out.println(metaClass3.equals(metaClass4));
		System.out.println(metaClass4.equals(metaClass3));
		System.out.println(metaClass4.equals(metaClass));
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy