/**
 * Hypergraph Completion
 * 
 * Copyright (C) 2008 Steffen Mazanek
 * This program is free software: you can redistribute it 
 * and/or modify it under the terms of the GNU General Public 
 * License as published by the Free Software Foundation, 
 * either version 3 of the License, or (at your option) any 
 * later version.
 * 
 * This program is distributed in the hope that it will be 
 * useful, but WITHOUT ANY WARRANTY; without even the implied 
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
 * PURPOSE. See the GNU General Public License for more 
 * details.
 * 
 * You should have received a copy of the GNU General Public 
 * License along with this program. If not, see 
 * http://www.gnu.org/licenses/.
 * 
 * Kontakt:
 * graphcompl@steffen-mazanek.de 
 */

import java.util.HashSet;
import java.util.Set;

import de.unibw.graphcompl.graph.Edge;
import de.unibw.graphcompl.graph.impl.EdgeCreatorImpl;
import de.unibw.graphcompl.graph.impl.EdgeImpl;
import de.unibw.graphcompl.graph.impl.NodeCreatorImpl;
import de.unibw.graphcompl.graph.impl.NodeImpl;
import de.unibw.graphcompl.graphgrammar.CNFGrammar;
import de.unibw.graphcompl.graphgrammar.CNFNonterminalProduction;
import de.unibw.graphcompl.graphgrammar.CNFTerminalProduction;
import de.unibw.graphcompl.parser.CYKParser;

/**
 * A test class with a main method. 
 * @author smazanek
 */
public class NSDTest {

	/**
	 * A graph with two isolated simple NSD statements is created. Then the completing
	 * parser is called three times. First zero edges are allowed to be added, second one
	 * edges is added. And finally it is used as a language generator generating all NSDs 
	 * of size 3.
	 * @param args
	 */
	public static void main(String[] args) {
		//construct an NSD graph consisting of two isolated statements
		Set<Edge> g=new HashSet<Edge>();
		g.add(new EdgeImpl("stmt",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4));
		g.add(new EdgeImpl("stmt",NodeImpl.n5,NodeImpl.n6,NodeImpl.n7,NodeImpl.n8));
		//add no edge 
		System.out.println(CYKParser.parse(NodeCreatorImpl.INSTANCE, EdgeCreatorImpl.INSTANCE, 
				getNSDGrammar(), g, 0));
		//add one edge 
		System.out.println(CYKParser.parse(NodeCreatorImpl.INSTANCE, EdgeCreatorImpl.INSTANCE, 
				getNSDGrammar(), g, 1));
		//generate NSD graphs of size 3 
		System.out.println(CYKParser.parse(NodeCreatorImpl.INSTANCE, EdgeCreatorImpl.INSTANCE, 
				getNSDGrammar(), new HashSet<Edge>(), 3));
		
	}

	/**
	 * This is the following example grammar for the language 
	 * of Nassi-Shneidermann diagrams (as described in several 
	 * DiaGen-papers):
	 * NSD(a,b,c,d) ::= Stmt(a,b,c,d)
	 * NSD(a,b,c,d) ::= Stmt(a,b,e,f) NSD(e,f,c,d)
	 * Stmt(a,b,c,d) ::= stmt(a,b,c,d)
	 * Stmt(a,b,c,d) ::= cond(a,b,e,f) NSD(e,g,c,h) NSD(g,f,h,d)
	 * Stmt(a,b,c,d) ::= while(a,b,e,f,c,g) NSD(e,f,g,d)
	 * Stmt(a,b,c,d) ::= repeat(a,e,f,g,c,d) NSD(e,b,f,g)
	 * Actually the grammar is provided in CNF.
	 * @author smazanek
	 */
	public static CNFGrammar getNSDGrammar() {
		Set<CNFTerminalProduction> tprods = new HashSet<CNFTerminalProduction>();
		Set<CNFNonterminalProduction> ntprods = new HashSet<CNFNonterminalProduction>();
		CNFGrammar grammar=new CNFGrammar("NSD",tprods,ntprods);

		tprods.add(new CNFTerminalProduction(				
				new EdgeImpl("Stmt",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("stmt",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4)));
		tprods.add(new CNFTerminalProduction(
				new EdgeImpl("NSD",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("stmt",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4)));
		tprods.add(new CNFTerminalProduction(
				new EdgeImpl("_02_cond",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("cond",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4)));
		tprods.add(new CNFTerminalProduction(
				new EdgeImpl("_03_while",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4,NodeImpl.n5,NodeImpl.n6),
				new EdgeImpl("while",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4,NodeImpl.n5,NodeImpl.n6)));
		tprods.add(new CNFTerminalProduction(
				new EdgeImpl("_04_repeat", NodeImpl.n1, NodeImpl.n5, NodeImpl.n6, NodeImpl.n7, NodeImpl.n3, NodeImpl.n4),
				new EdgeImpl("repeat", NodeImpl.n1, NodeImpl.n5, NodeImpl.n6, NodeImpl.n7, NodeImpl.n3, NodeImpl.n4)));

		ntprods.add(new CNFNonterminalProduction(
				new EdgeImpl("Stmt",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("_01_cond_NSD",NodeImpl.n1,NodeImpl.n2,NodeImpl.n5,NodeImpl.n6,NodeImpl.n3,NodeImpl.n7),
				new EdgeImpl("NSD",NodeImpl.n5,NodeImpl.n6,NodeImpl.n7,NodeImpl.n4)));
		ntprods.add(new CNFNonterminalProduction(
				new EdgeImpl("NSD",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("_01_cond_NSD",NodeImpl.n1,NodeImpl.n2,NodeImpl.n5,NodeImpl.n6,NodeImpl.n3,NodeImpl.n7),
				new EdgeImpl("NSD",NodeImpl.n5,NodeImpl.n6,NodeImpl.n7,NodeImpl.n4)));
		ntprods.add(new CNFNonterminalProduction(
				new EdgeImpl("_01_cond_NSD",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4,NodeImpl.n5,NodeImpl.n6),
				new EdgeImpl("_02_cond",NodeImpl.n1,NodeImpl.n2,NodeImpl.n7,NodeImpl.n4),
				new EdgeImpl("NSD",NodeImpl.n7,NodeImpl.n3,NodeImpl.n5,NodeImpl.n6)));
		ntprods.add(new CNFNonterminalProduction(
				new EdgeImpl("NSD",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("_03_while",NodeImpl.n1,NodeImpl.n2,NodeImpl.n5,NodeImpl.n6,NodeImpl.n3,NodeImpl.n7),
				new EdgeImpl("NSD",NodeImpl.n5,NodeImpl.n6,NodeImpl.n7,NodeImpl.n4)));
		ntprods.add(new CNFNonterminalProduction(
				new EdgeImpl("Stmt",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("_03_while",NodeImpl.n1,NodeImpl.n2,NodeImpl.n5,NodeImpl.n6,NodeImpl.n3,NodeImpl.n7),
				new EdgeImpl("NSD",NodeImpl.n5,NodeImpl.n6,NodeImpl.n7,NodeImpl.n4)));
		ntprods.add(new CNFNonterminalProduction(
				new EdgeImpl("NSD", NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("_04_repeat", NodeImpl.n1,NodeImpl.n5,NodeImpl.n6,NodeImpl.n7,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("NSD", NodeImpl.n5,NodeImpl.n2,NodeImpl.n6,NodeImpl.n7)));
		ntprods.add(new CNFNonterminalProduction(
				new EdgeImpl("Stmt", NodeImpl.n1, NodeImpl.n2, NodeImpl.n3, NodeImpl.n4),
				new EdgeImpl("_04_repeat", NodeImpl.n1,NodeImpl.n5,NodeImpl.n6,NodeImpl.n7,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("NSD", NodeImpl.n5,NodeImpl.n2,NodeImpl.n6,NodeImpl.n7)));
		ntprods.add(new CNFNonterminalProduction(
				new EdgeImpl("NSD",NodeImpl.n1,NodeImpl.n2,NodeImpl.n3,NodeImpl.n4),
				new EdgeImpl("Stmt",NodeImpl.n1,NodeImpl.n2,NodeImpl.n5,NodeImpl.n6),
				new EdgeImpl("NSD",NodeImpl.n5,NodeImpl.n6,NodeImpl.n3,NodeImpl.n4)));

		return grammar;
	}
}

