/* -*-Java-*- */

/* 
 * Copyright (C) 2007  Anders Nilsson <anders.nilsson@cs.lth.se>
 *
 * This file is part of XmlSchemaCompiler.
 */

import java.io.*;
import java.util.*;

aspect AbsGrammarGeneration {
    void ASTNode.genAbsGrammar(PrintStream pStream) {
		for (int i=0; i<getNumChild(); i++) {
			getChild(i).genAbsGrammar(pStream);
		}
    }

    public void Start.genAbsGrammar(PrintStream pStream) {
		pStream.println("// Predefined types");
		pStream.println("Start ::= Specification;");
        pStream.println("Specification ::= XmlHeader Element*;");
        pStream.println("XmlHeader ::=;");
		pStream.println("abstract Thing : ComplexElement ::=;");
		pStream.println("abstract Element;");
 		pStream.println("ComplexElement : Element ::=  OwlIdentifier Attribute* Element*;");
		pStream.println("ValueElement : ComplexElement;");
		pStream.println("abstract SimpleElement : Element;");
		pStream.println("StringElement : SimpleElement ::= <IDENTIFIER>;");
		pStream.println("IntElement : SimpleElement ::= <INTEGER_LITERAL>;");
		pStream.println("FloatElement : SimpleElement ::= <FLOAT_LITERAL>;");
// 		pStream.println("ClassUse : Thing  ::= /decl:Thing/;");
		pStream.println("Attribute ::= Value;");
// 		pStream.println("RdfDatatype : Attribute ::= ;");
// 		pStream.println("RdfId : Attribute ::= ;");
// 		pStream.println("Xmlns : Attribute ::= ;");
// 		pStream.println("XmlnsProtege : Attribute ::= ;");
// 		pStream.println("XmlnsRdf : Attribute ::= ;");
// 		pStream.println("XmlnsXsd : Attribute ::= ;");
// 		pStream.println("XmlnsRdfs : Attribute ::= ;");
// 		pStream.println("XmlnsOwl : Attribute ::= ;");
// 		pStream.println("XmlnsDaml : Attribute ::= ;");
// 		pStream.println("XmlnsP1 : Attribute ::= ;");
// 		pStream.println("XmlnsDc : Attribute ::= ;");
// 		pStream.println("XmlBase : Attribute ::= ;");
// 		pStream.println("RdfResource : Attribute ::= ;");
// 		pStream.println("RdfAbout : Attribute ::= ;");
// 		pStream.println("RdfParseType : Attribute ::= ;");
// 		pStream.println("Version : Attribute ::= ;");
		pStream.println("Value ::= <STRING_LITERAL>;");
		pStream.println("OwlIdentifier ::= <IDENTIFIER>;");
		pStream.println("AttrValue ::= <STRING_LITERAL>;");
		pStream.println();
		pStream.println("// Generated types");
		super.genAbsGrammar(pStream);
    }


}

aspect GenJavaCC {
	void ASTNode.genJavaCC(PrintStream pStream) {
		for (int i=0; i<getNumChild(); i++) {
			getChild(i).genJavaCC(pStream);
		}
	}

	public void Start.genJavaCC(PrintStream pStream) {
        genJavaCCHeader(pStream);
        genJavaCCTokens(pStream);
        genJavaCCLiterals(pStream);
        genJavaCCIdentifiers(pStream);
        genJavaCCSeparators(pStream);
        genJavaCCOperators(pStream);
        pStream.println("Start Start() #Start : {}");
        pStream.println("{");
        pStream.println("  Specification()");
        pStream.println("  { return jjThis; }");
        pStream.println("}");
        pStream.println();
        pStream.println("void Specification() #Specification : {}");
        pStream.println("{");
        pStream.println("  XmlHeader()");
        pStream.println("  ElementList()");
        pStream.println("}");
        pStream.println();
        pStream.println("void XmlHeader() #XmlHeader : {}");
        pStream.println("{");
        pStream.println("  \"<?\" <XML> AttributeList() \"?>\"");
        pStream.println("}");
        pStream.println();
        pStream.println("void ElementList() #List : {}");
        pStream.println("{");
        pStream.println("  (Element())*");
        pStream.println("}");
        pStream.println();
        pStream.println("void AttributeList() #List : {}");
        pStream.println("{");
        pStream.println("  (Attribute())*");
        pStream.println("}");
        pStream.println();
        pStream.println("void AttValue() #AttValue : { Token t; }");
        pStream.println("{");
        pStream.println("    t = <STRING_LITERAL>");
        pStream.println("        {jjtThis.setSTRING_LITERAL(t.image);}");
        pStream.println("}");
        pStream.println("void Element()  : {}");
        pStream.println("{");
        pStream.println("  \"<\"");
        Iterator iter = elementTypes().values().iterator();
        if (iter.hasNext()) {
            pStream.println("  "+fixName(((XsElement) iter.next()).name())+"()");
        }
        while (iter.hasNext()) {
            pStream.println("  | "+fixName(((XsElement) iter.next()).name())+"()");
        }
        pStream.println("  ");
        pStream.println("}");
        pStream.println();
        pStream.println("void Attribute()  : {}");
        pStream.println("{");
        iter = attributeTypes().values().iterator();
        if (iter.hasNext()) {
            pStream.println("  "+fixName(((XsAttribute) iter.next()).name())+"()");
        }
        while (iter.hasNext()) {
            pStream.println("  | "+fixName(((XsAttribute) iter.next()).name())+"()");
        }
        pStream.println("  ");
        pStream.println("}");
        pStream.println();

        // This is somewhat of a hack, but seems to work work as an
        // easy way to eliminate duplicate attribute
        // declarations. Anders Nilsson 070808.
        Hashtable h = elementTypes();
        h.putAll(attributeTypes());
        iter = h.values().iterator();
        while (iter.hasNext()) {
            ((ASTNode) iter.next()).genJavaCC(pStream);
        }
//         super.genJavaCC(pStream);
	}

    void XsElement.genJavaCC(PrintStream pStream) {
        if (hasName()) { // If not, it's just a reference to an element declaration
            String name = name();
            pStream.println("void "+name+"() #"+name+" : {}");
            pStream.println("{");

            pStream.println("   <"+name+"> AttributeList() \">\"");
//             pStream.println("  \"<\" <"+name+"> AttributeList() \">\"");
            pStream.println("  ElementList()");
            pStream.println("  \"</\" <"+name+">  \">\"");
//             pStream.println("  \"<\" <"+name.toUpperCase()+"> AttributeList() \">\"");
//             pStream.println("  ElementList()");
//             pStream.println("  \"</\" <"+name.toUpperCase()+">  \">\"");
            pStream.println("}");
        }
    }

    void XsAttribute.genJavaCC(PrintStream pStream) {
        if (hasName()) { // If not, it's just a reference to an attribute declaration
            String name = fixName(name());
            pStream.println("void "+name+"() #"+name+" : {}");
            pStream.println("{");
            pStream.println("  <"+name+"> \"=\" AttValue()");
//             pStream.println("  <"+name.toUpperCase()+"> \"=\" AttValue()");
            pStream.println("}");
        }
    }

    void Start.genJavaCCTokens(PrintStream pStream) {
		pStream.println("<DEFAULT, BOUNDS> TOKEN : /* Reserved Words */");
		pStream.println("{");
        Hashtable h = elementTypes();
        h.putAll(attributeTypes());
        Iterator iter = h.values().iterator();
        pStream.println("   <XML\t\t: \"XML\">");
        while (iter.hasNext()) {
            String name = ((ComplexElement) iter.next()).name();
            pStream.println(" | <"+fixName(name)+
//             pStream.println(" | <"+fixName(name).toUpperCase()+
                            "\t\t: \""+name+"\" >");
        }
//         iter = attributeTypes().iterator();
//         while (iter.hasNext()) {            
//             String name = ((ComplexElement) iter.next()).name();
//             pStream.println(" | <"+fixName(name).toUpperCase()+
//                             "\t\t: \""+name+"\" >");
//         }        
		pStream.println("}// Reserved Words");
        pStream.println();
    }
}

aspect Types {
    Hashtable Start.elementTypes() {
        Hashtable h = new Hashtable();
        return elementTypes(h);
    }

    syn Hashtable ASTNode.elementTypes(Hashtable h) {
        for (int i=0; i<getNumChild(); i++) {
            getChild(i).elementTypes(h);
        }
        return h;
    }

    eq XsElement.elementTypes(Hashtable h) {
        if (hasName()) {
            h.put(name(),this);
        }
        super.elementTypes(h);
        return h;
    }
    
    Hashtable Start.attributeTypes() {
        Hashtable h = new Hashtable();
        return attributeTypes(h);
    }

    syn Hashtable ASTNode.attributeTypes(Hashtable h) {
        for (int i=0; i<getNumChild(); i++) {
            getChild(i).attributeTypes(h);
        }
        return h;
    }

    eq XsAttribute.attributeTypes(Hashtable h) {
        if (hasName()) {
            h.put(name(),this);
        }
        super.attributeTypes(h);
        return h;
    }
    
}

aspect Misc {
	syn String ComplexElement.name() {
		for (int i=0; i<getNumAttribute(); i++) {
			if (getAttribute(i) instanceof Name) {
				return getAttribute(i).getAttValue().getSTRING_LITERAL().
                    replace("\""," ").trim();
			}
		}
		// OK, no name found so let's report that
		return "NoNameFound";
	}

	syn boolean ComplexElement.hasName() {
		for (int i=0; i<getNumAttribute(); i++) {
			if (getAttribute(i) instanceof Name) {
				return true;
			}
		}
		// OK, no name found so let's report that
		return false;
	}

    static String ASTNode.fixName(String s) {
        if (s.equals("class")) {
            return "clazz";
        }
        s = s.replace("-","_");
        return s;
    }
}


// aspect GenAspects {
// 	public void Start.genAspects(PrintStream pStream) {
// 		pStream.println();
// 		pStream.println("import java.io.PrintStream;");
// 		pStream.println();
// 		genRewrites(pStream);
// 		genMisc(pStream);
// 		genPrettyPrinter(pStream);
// 	}
// }

// aspect GenPrettyPrinter {
// 	public void ASTNode.genPrettyPrinter(PrintStream pStream) {
// 		for (int i=0; i<getNumChild(); i++) {
// 			getChild(i).genPrettyPrinter(pStream);
// 		}
// 	}

// 	public void Start.genPrettyPrinter(PrintStream pStream) {
// 		pStream.println();
// 		pStream.println("aspect PrettyPrinter {");
// 		pStream.println("  public void ASTNode.prettyPrint(String indent, PrintStream pStream) {");
// 		pStream.println("    for (int i=0; i<getNumChild(); i++) {");
// 		pStream.println("      getChild(i).prettyPrint(indent,pStream);");
// 		pStream.println("    }");
// 		pStream.println("  }\n");
// 		pStream.println("  public void Start.prettyPrint(String indent, PrintStream pStream) {");
// 		pStream.println("    for (int i=0; i<getNumElement(); i++) {");
// 		pStream.println("      getElement(i).prettyPrint(indent,pStream);");
// 		pStream.println("    }");
// 		pStream.println("  }\n");
// 		pStream.println("  syn String Attribute.id() = \"\";");
// 		pStream.println("  eq RdfId.id() = \"Rdf:ID\";");
// 		pStream.println("  eq RdfDatatype.id() = \"Rdf:datatype\";");
// 		pStream.println("  eq RdfResource.id() = \"Rdf:resource\";");
// 		pStream.println("  public void Attribute.prettyPrint(String indent, PrintStream pStream) {");
// 		pStream.println("    System.out.print(\" \"+id()+\"=\"+getValue().getSTRING_LITERAL());");
// 		pStream.println("  }\n");
// 		pStream.println(ind(1)+"public void ValueElement.prettyPrint(String indent, PrintStream pStream) {");
// 		pStream.println(ind(2)+"System.out.print(indent+\"<value \");");
// 		pStream.println(ind(2)+"for (int i=0; i<getNumAttribute(); i++) {");
// 		pStream.println(ind(3)+"getAttribute(i).prettyPrint(indent,pStream);");
// 		pStream.println(ind(2)+"}");
// 		pStream.println(ind(2)+"System.out.println(\">\");");
// 		pStream.println(ind(2)+"System.out.println(indent+\"  \"+value());");
// 		pStream.println(ind(2)+"System.out.println(indent+\"</value>\");");
// 		pStream.println(ind(1)+"}\n");
// 		// Generate prettyprinter for ClassUse
// 		pStream.println(ind(1)+"public void ClassUse.prettyPrint(String indent, PrintStream pStream) {");
// 		pStream.println(ind(2)+"System.out.print(indent+\"<\"+name());");
// 		pStream.println(ind(2)+"for (int i=0; i<getNumAttribute(); i++) {");
// 		pStream.println(ind(3)+"getAttribute(i).prettyPrint(indent,pStream);");
// 		pStream.println(ind(2)+"}");
// 		pStream.println(ind(2)+"System.out.println(\"/>\");");
// 		pStream.println(ind(1)+"}\n");
// 		super.genPrettyPrinter(pStream);
// 		pStream.println("}\n");
// 	}

// 	public void OwlClassDecl.genPrettyPrinter(PrintStream pStream) {
// 		// Generate prettyprinter for class declaration
// 		pStream.print(ind(1)+"public void "+name());
// 		pStream.println(".prettyPrint(String indent, PrintStream pStream) {");
// 		pStream.println(ind(2)+"System.out.print(indent+\"<"+name()+"\");");
// 		pStream.println(ind(2)+"for (int i=0; i<getNumAttribute(); i++) {");
// 		pStream.println(ind(3)+"getAttribute(i).prettyPrint(indent,pStream);");
// 		pStream.println(ind(2)+"}");
// 		pStream.println("System.out.println(\">\");");
// 		pStream.println(ind(2)+"String childIndent = indent + \"  \";");
// // 		Restrictions restr = getRestrictions();
// // 		for (int i=0; i<restr.getNumOwlRestriction(); i++) {
// // 			OwlRestriction r = restr.getOwlRestriction(i);
// // 			pStream.println(ind(2)+"System.out.println(childIndent+\"<has"+
// // 							r.name()+">\");");
// // 			pStream.println(ind(2)+"for (int i=0; i<getNum"+r.name()+"(); i++) {");
// // 			pStream.println(ind(3)+"get"+r.name()+
// // 							"(i).prettyPrint(childIndent+\"  \",pStream);");
// // 			pStream.println(ind(2)+"}");
// // 			pStream.println(ind(2)+"System.out.println(childIndent+\"</has"+
// // 							r.name()+">\");");
// // 		}
// 		pStream.println(ind(2)+"for (int i=0; i<getNumElement(); i++) {");
// 		pStream.println(ind(3)+"getElement(i).prettyPrint(childIndent,pStream);");
// 		pStream.println(ind(2)+"}");
// 		pStream.println(ind(1)+"System.out.println(indent+\"</"+name()+">\");");
// 		pStream.println(ind(1)+"}\n");		
// 	}
// }

// aspect GenRewrites {

//     public void ASTNode.genRewrites(PrintStream pStream) {
// 		for (int i=0; i<getNumChild(); i++) {
// 			getChild(i).genRewrites(pStream);
// 		}
//     }

// 	public void Start.genRewrites(PrintStream pStream) {
// 		pStream.println();
// 		pStream.println("aspect Rewrites {");
// 		pStream.println(ind(1)+"rewrite ComplexElement {");
// 		pStream.println(ind(2)+"when (!(this instanceof ClassUse) && getOwlIdentifier().getIDENTIFIER().equals(\"value\") && !(this instanceof ValueElement))");
// 		pStream.println(ind(3)+"to ValueElement {");
// 		pStream.println(ind(3)+"ValueElement node = new ValueElement();");
// 		pStream.println(ind(3)+"node.setOwlIdentifier(getOwlIdentifier());");
// 		pStream.println(ind(3)+"node.setAttributeList(getAttributeList());");
// 		pStream.println(ind(3)+"node.setElementList(getElementList());");
// 		pStream.println(ind(3)+"return node;");
// 		pStream.println(ind(2)+"}");
// 		pStream.println(ind(1)+"}");

// 		// TEMPORARY!!!!!
// 		// Rewrite isSkillOf/hasSkill/hasProperty/isPropertyOf to ClassUse
// 		pStream.println(ind(1)+"rewrite ComplexElement {");
// 		pStream.println(ind(2)+"when ((name().equals(\"hasSkill\")");
// 		pStream.println(ind(2)+"|| name().equals(\"isSkillOf\"))");
// 		pStream.println("&& getNumAttribute() > 0 && getAttribute(0) instanceof RdfResource)");
// 		pStream.println(ind(2)+"to ClassUse {");
// 		pStream.println(ind(3)+"ClassUse use = new ClassUse();");
// 		pStream.println(ind(3)+"String att = getAttribute(0).name();");
// 		pStream.println(ind(3)+"use.setOwlIdentifier(new OwlIdentifier(att.substring(att.indexOf('#')+1,att.indexOf('_'))));");
// 		pStream.println(ind(3)+"use.setAttributeList(getAttributeList());");
// 		pStream.println(ind(3)+"use.setElementList(new List());");
// 		pStream.println(ind(3)+"return use;");
// 		pStream.println(ind(2)+"}");
// 		pStream.println(ind(1)+"}");
	  

// 		super.genRewrites(pStream);
// 		pStream.println("}");
// 	}

// 	public void OwlClassDecl.genRewrites(PrintStream pStream) {
// 		String ind = "  ";
// 		int ix = 0;
// 		// Specialize ComplexElements to the actual class in the ontology
// 		pStream.println(ind(1)+"rewrite ComplexElement {");
// 		pStream.println(ind(2)+"when (!(this instanceof ClassUse) && getOwlIdentifier().getIDENTIFIER().equals(\""+
// 						name()+"\") && !(this instanceof Thing))");
// 		pStream.println(ind(3)+"to "+name()+" {");

// 		pStream.println(ind(3)+name()+" node = new "+name()+"();");
// 		pStream.println(ind(3)+"node.setOwlIdentifier(getOwlIdentifier());");
// 		pStream.println(ind(3)+"node.setAttributeList(getAttributeList());");
//  		pStream.println(ind(3)+"node.setElementList(getElementList());");
// // 		Restrictions restr = getRestrictions();
// // 		pStream.println(ind(3)+"List l, remain;");
// // 		pStream.println(ind(3)+"remain = new List();");
// // 		for (int i=0; i<restr.getNumOwlRestriction(); i++) {
// // 			OwlRestriction r = restr.getOwlRestriction(i);
// // 			pStream.println(ind(3)+"l = new List();");
// // 			pStream.println(ind(3)+"for (int i=0; i<getNumElement(); i++) {");
// // 			pStream.println(ind(4)+"ComplexElement e = (ComplexElement) getElement(i);");
// // 			pStream.println(ind(4)+"if (e.getNumElement() > 0 && e.getElement(0) instanceof "+r.name()+" ) {");
// // 			pStream.println(ind(5)+"l.add(e.getElement(0));");
// // 			pStream.println(ind(4)+"}");
// // 			pStream.println(ind(3)+"}");
// // 			if (r.allValuesFrom()) {
// // 				pStream.println(ind(3)+"node.set"+r.name()+"List(l);");
// // 			} else {
// // 				pStream.println(ind(3)+r.name()+" c"+ix+" = new "+r.name()+"();");
// // 				pStream.println(ind(3)+"node.set"+r.name()+"(c"+(ix++)+");");
// // 			}
// // 		}
// // 		pStream.println(ind(3)+"for (int i=0; i<getNumElement(); i++) {");
// // 		pStream.println(ind(4)+"if (getElement(i) instanceof ValueElement) {");
// // 		pStream.println(ind(5)+"remain.add(getElement(i));");
// // 		pStream.println(ind(4)+"}");
// // 		pStream.println(ind(3)+"}");
// //   		pStream.println(ind(3)+"node.setElementList(remain);");
// 		pStream.println(ind(3)+"return node;");
// 		pStream.println(ind(2)+"}");
// 		pStream.println(ind(1)+"}");
// 		pStream.println();
// 		// Rearrange device nodes on the AST to get away from the
// 		// current diagonal style from Protege
// 		pStream.println(ind(1)+"rewrite "+name()+" {");
// 		pStream.println(ind(2)+"when (!isTopElement())");
// 		pStream.println(ind(2)+"to ClassUse {");
// 		pStream.println(ind(3)+"ClassUse use = new ClassUse();");
// 		pStream.println(ind(3)+"use.setOwlIdentifier(new OwlIdentifier(\""+name()+"\"));");
// 		pStream.println(ind(3)+"use.setAttributeList(new List().add(new RdfResource(getAttribute(0).getValue())));");
// 		pStream.println(ind(3)+"use.setElementList(new List());");
// 		pStream.println(ind(3)+"getStart().addElement(this);");
// 		pStream.println(ind(3)+"return use;");
// 		pStream.println(ind(2)+"}");
// 		pStream.println(ind(1)+"}");
// 	}

// }

// aspect GenMisc {

//     public void ASTNode.genMisc(PrintStream pStream) {
// 		for (int i=0; i<getNumChild(); i++) {
// 			getChild(i).genMisc(pStream);
// 		}
//     }

// 	public void Start.genMisc(PrintStream pStream) {
// 		pStream.println();
// 		pStream.println("aspect Misc {");
// 		pStream.println();
// 		pStream.println(ind(1)+"String ValueElement.value() {");
// 		pStream.println(ind(2)+"StringBuffer b = new StringBuffer();");
// 		pStream.println(ind(2)+"for (int i=0; i<getNumElement(); i++) {");
// 		pStream.println(ind(3)+"b.append(((SimpleElement) getElement(i)).value());");
// 		pStream.println(ind(3)+"b.append(\" \");");
// 		pStream.println(ind(2)+"}");
// 		pStream.println(ind(2)+"return b.toString().trim();");
// 		pStream.println(ind(1)+"}");
// 		pStream.println();
// 		pStream.println(ind(1)+"syn String SimpleElement.value() = \"\";");
// 		pStream.println(ind(1)+"eq StringElement.value() = getIDENTIFIER();");
// 		pStream.println(ind(1)+"eq IntElement.value() = getINTEGER_LITERAL();");
// 		pStream.println(ind(1)+"eq FloatElement.value() = getFLOAT_LITERAL();");
		
// 		pStream.println(ind(1)+"boolean Thing.isTopElement() {");
// 		pStream.println(ind(2)+"return getParent().getParent() instanceof Start;");
// 		pStream.println(ind(1)+"}");

// 		pStream.println(ind(1)+"Start ASTNode.getStart() {");
// 		pStream.println(ind(2)+"return getParent().getStart();");
// 		pStream.println(ind(1)+"}");
// 		pStream.println(ind(1)+"Start Start.getStart() {");
// 		pStream.println(ind(2)+"return this;");
// 		pStream.println(ind(1)+"}");
		
// 		pStream.println(ind(1)+"String ComplexElement.name() {");
// 		pStream.println(ind(2)+"return getOwlIdentifier().getIDENTIFIER();");
// 		pStream.println(ind(1)+"}");
// 		pStream.println(ind(1)+"String Attribute.name() {");
// 		pStream.println(ind(2)+"return getValue().getSTRING_LITERAL();");
// 		pStream.println(ind(1)+"}");


// 		super.genMisc(pStream);
// 		pStream.println("}");
// 	}

// }

aspect ParserGen {
	public void Start.genParser(PrintStream pStream) {
		pStream.println("import java.io.FileNotFoundException;");
		pStream.println("import java.io.FileReader;");
		pStream.println("import java.io.InputStreamReader;");
		pStream.println("import java.io.Reader;");
		pStream.println("");
		pStream.println("import AST.XmlParser;");
		pStream.println("import AST.ParseException;");
		pStream.println("import AST.Start;");
		pStream.println("");
		pStream.println("public class Parser {");
		pStream.println();
		pStream.println("	protected static Start parse(String args[]) {");
		pStream.println("		Reader r = getReader(args);");
		pStream.println("		Start ast = null;");
		pStream.println("		try {");
		pStream.println("			XmlParser parser = new XmlParser(r);");
		pStream.println();
		pStream.println("			ast = parser.Start();");
		pStream.println("		} catch (ParseException e) {");
		pStream.println("			System.out.println(e.getMessage());");
		pStream.println("		}");
		pStream.println("		return ast;");
		pStream.println("	}");
		pStream.println();
		pStream.println("	private static Reader getReader(String[] args) {");
		pStream.println("		Reader r = null;");
		pStream.println("		if (args.length != 1) {");
		pStream.println("			r = new InputStreamReader(System.in);");
		pStream.println("		} else {");
		pStream.println("			try {");
		pStream.println("				r = new FileReader(args[0]);");
		pStream.println("			} catch (FileNotFoundException e1) {");
		pStream.println("				System.err.println(\"Dumper: file \" + args[0] + \" not found\");");
		pStream.println("			}");
		pStream.println("		}");
		pStream.println("		return r;");
		pStream.println("	}");
		pStream.println("}");
	}
}