package ca.uwaterloo.joos.ast.decl;

import java.util.List;

import ca.uwaterloo.joos.ast.ASTNode;
import ca.uwaterloo.joos.ast.Modifiers;
import ca.uwaterloo.joos.ast.body.ClassBody;
import ca.uwaterloo.joos.ast.body.TypeBody;
import ca.uwaterloo.joos.ast.descriptor.ChildDescriptor;
import ca.uwaterloo.joos.ast.descriptor.ChildListDescriptor;
import ca.uwaterloo.joos.ast.type.ReferenceType;
import ca.uwaterloo.joos.parser.ParseTree.LeafNode;
import ca.uwaterloo.joos.parser.ParseTree.Node;
import ca.uwaterloo.joos.parser.ParseTree.TreeNode;

public abstract class TypeDeclaration extends ASTNode {

	protected static final ChildDescriptor MODIFIERS = new ChildDescriptor(Modifiers.class);
	protected static final ChildListDescriptor INTERFACES = new ChildListDescriptor(ReferenceType.class);
	protected static final ChildDescriptor BODY = new ChildDescriptor(TypeBody.class);

	public TypeDeclaration(Node node, ASTNode parent) throws Exception {
		super(node, parent);
	}

	public Modifiers getModifiers() throws ChildTypeUnmatchException {
		return (Modifiers) this.getChildByDescriptor(TypeDeclaration.MODIFIERS);
	}

	@SuppressWarnings("unchecked")
	public List<ReferenceType> getInterfaces() throws ChildTypeUnmatchException {
		return (List<ReferenceType>) this.getChildByDescriptor(TypeDeclaration.INTERFACES);
	}

	public TypeBody getBody() throws ChildTypeUnmatchException {
		return (TypeBody) this.getChildByDescriptor(TypeDeclaration.BODY);
	}

	@Override
	public List<Node> processTreeNode(TreeNode treeNode) throws Exception {
		if (treeNode.productionRule.getLefthand().equals("modifiers")) {
			Modifiers modifiers = new Modifiers(treeNode, this);
			addChild(MODIFIERS, modifiers);
		} else if (treeNode.productionRule.getLefthand().equals("interface")) {
			// TODO interface declaration do not use interface as keyword
			ReferenceType interfaceType = new ReferenceType(treeNode, this);
			addChild(INTERFACES, interfaceType);
		} else if (treeNode.productionRule.getLefthand().equals("classbody")) {
			ClassBody body = new ClassBody(treeNode, this);
			addChild(BODY, body);
		} else {
			return super.processTreeNode(treeNode);
		}
		return null;
	}

	@Override
	public void processLeafNode(LeafNode leafNode) throws Exception {
		if (leafNode.token.getKind().equals("ID")) {
			setIdentifier(leafNode.token.getLexeme());
		}
	}
}

@@ -173,24 +173,73 @@
 .ClassBody;%0A
+import ca.uwaterloo.joos.ast.body.InterfaceBody;%0A
 import ca.uw
@@ -266,24 +266,24 @@
 y.TypeBody;%0A
-
 import ca.uw
@@ -782,24 +782,23 @@
 riptor I
-NTERFACE
+MPLEMNT
 S = new 
@@ -1353,24 +1353,23 @@
 ration.I
-NTERFACE
+MPLEMNT
 S);%0A%09%7D%0A%0A
@@ -1744,24 +1744,29 @@
 ifiers);%0A%09%09%7D
+%0A%09%09//
  else if (tr
@@ -1828,13 +1828,15 @@
 ) %7B%0A
-%09
 %09%09//
+ //
  TOD
@@ -1893,17 +1893,19 @@
 yword%0A%09%09
-%09
+// 
 Referenc
@@ -1955,33 +1955,35 @@
 eNode, this);%0A%09%09
-%09
+// 
 addChild(INTERFA
@@ -2001,26 +2001,31 @@
 aceType);%0A%09%09
-%7D 
+// %7D%0A%09%09
 else if (tre
@@ -2158,16 +2158,178 @@
  body);%0A
+%09%09%7D else if (treeNode.productionRule.getLefthand().equals(%22interfacebody%22)) %7B%0A%09%09%09InterfaceBody body = new InterfaceBody(treeNode, this);%0A%09%09%09addChild(BODY, body);%0A
 %09%09%7D else

add interface implement