view src/nabble/naml/compiler/JavaNamespace.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line source

package nabble.naml.compiler;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import fschmidt.util.java.Computable;
import fschmidt.util.java.Memoizer;


final class JavaNamespace implements GenericNamespace {
	final Class cls;
	private final boolean isGlobal;
	private final boolean isTransparent;
	final String name;
	final Class extensionTarget;
	final Constructor extensionConstructor;
	private final List<String> names = new ArrayList<String>();

	private JavaNamespace(Class<?> cls,Namespace namespace) {
		this.cls = cls;
		this.name = namespace.name();
		this.isGlobal = namespace.global();
		this.isTransparent = namespace.transparent();
		this.extensionTarget = null;
		this.extensionConstructor = null;
		addNames(cls);
	}

	private JavaNamespace(Class<?> cls,NamespaceExtension namespaceExt) {
		this.cls = cls;
		this.name = namespaceExt.name();
		this.extensionTarget = namespaceExt.target();
		this.isGlobal = getNamespace(extensionTarget).isGlobal;
		this.isTransparent = true;
		try {
			this.extensionConstructor = cls.getConstructor(extensionTarget);
		} catch(NoSuchMethodException e) {
			throw new RuntimeException(e);
		}
		addNames(cls);
	}

	@Override public boolean isGlobal() {
		return isGlobal;
	}

	@Override public boolean isTransparent() {
		return isTransparent;
	}

	@Override public List<String> names() {
		return names;
	}

	@Override public String getId() {
		return cls.getName();
	}

	private void addNames(Class<?> c) {
		if( c==null )
			return;
		Namespace namespace = c.getAnnotation(Namespace.class);
		if( namespace != null ) {
			names.add( namespace.name() );
		}
		NamespaceExtension namespaceExt = c.getAnnotation(NamespaceExtension.class);
		if( namespaceExt != null )
			names.add(namespaceExt.name());
		addNames(c.getSuperclass());
/*
		for( Class ifc : c.getInterfaces() ) {
			addNames(ifc);
		}
*/
	}

	public String toString() {
		return name;
	}


	private static Memoizer<Class<?>,JavaNamespace> cache = new Memoizer<Class<?>,JavaNamespace>(new Computable<Class<?>,JavaNamespace>() {
		public JavaNamespace get(Class<?> cls) {
			Namespace namespace = cls.getAnnotation(Namespace.class);
			if( namespace != null )
				return new JavaNamespace(cls,namespace);
			NamespaceExtension namespaceExt = cls.getAnnotation(NamespaceExtension.class);
			if( namespaceExt != null )
				return new JavaNamespace(cls,namespaceExt);
			throw new TemplateRuntimeException(""+cls+" isn't annotated as a Namespace or NamespaceExtension");
		}
	});

	static JavaNamespace getNamespace(Class cls) {
		return cache.get(cls);
	}

	static JavaNamespace getNamespaceExt(Class cls) {
		JavaNamespace ns = getNamespace(cls);
		if( ns.extensionTarget == null )
			throw new RuntimeException(""+cls+" isn't NamespaceExtension");
		return ns;
	}

}