View Javadoc

1   /*
2    * Zemucan: A Syntax Assistant for DB2
3    * Copyright (C) 2009, 2010 Andres Gomez Casanova
4    *
5    * This file is part of Zemucan.
6    *
7    * Zemucan is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as published by
9    * the Free Software Foundation; either version 3 of the License, or
10   * (at your option) any later version.
11   *
12   * Zemucan is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public License
18   * along with this library; if not, see <http://www.gnu.org/licenses/>.
19   *
20   * Contact:
21   * a n g o c a  at  y a h o o  dot  c o m
22   * Cra. 45 No 61 - 31, Bogota, Colombia.
23   *
24   * Author:   $LastChangedBy: angoca $:
25   * Date:     $LastChangedDate: 2011-03-06 23:10:20 -0500 (dom, 06 mar 2011) $:
26   * Revision: $LastChangedRevision: 1917 $:
27   * URL:      $HeadURL: https://zemucan.svn.sourceforge.net/svnroot/zemucan/branches/zemucan_v1/source-code/grammarReaderImplXML/src/main/java/name/angoca/zemucan/grammarReader/impl/xml/ImplementationXMLGrammarReader.java $:
28   */
29  package name.angoca.zemucan.grammarReader.impl.xml;
30  
31  import java.io.File;
32  import java.io.IOException;
33  import java.io.InputStream;
34  import java.util.ArrayList;
35  import java.util.List;
36  
37  import javax.xml.XMLConstants;
38  import javax.xml.parsers.DocumentBuilder;
39  import javax.xml.parsers.DocumentBuilderFactory;
40  import javax.xml.parsers.ParserConfigurationException;
41  import javax.xml.transform.Source;
42  import javax.xml.transform.stream.StreamSource;
43  import javax.xml.validation.Schema;
44  import javax.xml.validation.SchemaFactory;
45  import javax.xml.validation.Validator;
46  
47  import name.angoca.zemucan.AbstractZemucanException;
48  import name.angoca.zemucan.ParameterNullException;
49  import name.angoca.zemucan.core.graph.model.Graph;
50  import name.angoca.zemucan.core.graph.model.StartingNode;
51  import name.angoca.zemucan.grammarReader.api.AbstractGrammarFileReaderException;
52  import name.angoca.zemucan.grammarReader.api.AbstractGrammarReaderException;
53  import name.angoca.zemucan.grammarReader.api.AbstractTwoPhaseGrammarReader;
54  import name.angoca.zemucan.grammarReader.api.DelimitersIncorrectlyDefinedException;
55  import name.angoca.zemucan.grammarReader.api.GeneralGrammarFileProblemException;
56  import name.angoca.zemucan.grammarReader.api.GrammarFileNotDefinedException;
57  import name.angoca.zemucan.grammarReader.api.GrammarReaderController;
58  import name.angoca.zemucan.tools.Constants;
59  import name.angoca.zemucan.tools.configurator.Configurator;
60  import name.angoca.zemucan.tools.file.FileReader;
61  
62  import org.slf4j.Logger;
63  import org.slf4j.LoggerFactory;
64  import org.w3c.dom.Attr;
65  import org.w3c.dom.Document;
66  import org.w3c.dom.Element;
67  import org.w3c.dom.NodeList;
68  import org.xml.sax.ErrorHandler;
69  import org.xml.sax.InputSource;
70  import org.xml.sax.SAXException;
71  import org.xml.sax.SAXParseException;
72  
73  /**
74   * This class deals with the XML errors.
75   * <p>
76   * <b>Control Version</b>
77   * <p>
78   * <ul>
79   * <li>1.0.0 Class creation</li>
80   * <li>1.0.1 Get stream</li>
81   * <li>1.0.2 Access to private object</li>
82   * <li>1.1.0 Extends two phase grammar reader.</li>
83   * </ul>
84   *
85   * @author Andres Gomez Casanova <a
86   *         href="mailto:a n g o c a at y a h o o dot c o m" >(AngocA)</a>
87   * @version 1.1.0 2010-10-30
88   */
89  class Handler implements ErrorHandler {
90  
91  	/**
92  	 * Logger.
93  	 */
94  	private static final Logger LOGGER = LoggerFactory.getLogger(Handler.class);
95  
96  	/**
97  	 * Process the message to show when an issue is detected.
98  	 *
99  	 * @param level
100 	 *            Message's level.
101 	 * @param exception
102 	 *            exception that explain the problem.
103 	 * @return The descriptive message.
104 	 */
105 	private String/* ! */createMessage(final String/* ! */level,
106 			final SAXParseException/* ! */exception) {
107 		String message = "There was " + level + " at the line "
108 				+ exception.getLineNumber() + " column "
109 				+ exception.getColumnNumber();
110 		final String filename = exception.getSystemId();
111 		if (filename != null) {
112 			message += " of file " + exception.getSystemId();
113 		} else {
114 			message += " from the input";
115 		}
116 		return message + ": " + exception.getMessage();
117 	}
118 
119 	/*
120 	 * (non-Javadoc)
121 	 *
122 	 * @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)
123 	 */
124 	@Override
125 	public void error(final SAXParseException/* ! */exception)
126 			throws SAXException {
127 		final String message = this.createMessage("an error", exception);
128 		Handler.LOGGER.error(message);
129 	}
130 
131 	/*
132 	 * (non-Javadoc)
133 	 *
134 	 * @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException )
135 	 */
136 	@Override
137 	public void fatalError(final SAXParseException exception)
138 			throws SAXException {
139 		final String message = this.createMessage("a problem", exception);
140 		Handler.LOGGER.error(message);
141 	}
142 
143 	/*
144 	 * (non-Javadoc)
145 	 *
146 	 * @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)
147 	 */
148 	@Override
149 	public void warning(final SAXParseException exception) throws SAXException {
150 		final String message = this.createMessage("an alert", exception);
151 		Handler.LOGGER.warn(message);
152 	}
153 }
154 
155 /**
156  * This class builds the graph from the content of the files.
157  * <p>
158  * Based on a tutorial that can be found in
159  * http://www.totheriver.com/learn/xml/xmltutorial.html
160  * <p>
161  * <b>Control Version</b>
162  * <p>
163  * <ul>
164  * <li>0.0.1 Class creation.</li>
165  * <li>0.0.2 Recommendations from PMD.</li>
166  * <li>0.0.3 Organized.</li>
167  * <li>0.0.4 License token.</li>
168  * <li>0.0.5 License token reserved.</li>
169  * <li>0.0.6 Ending node after create table.</li>
170  * <li>0.1.0 Use of XML to create the graph.</li>
171  * <li>0.1.1 Help Token.</li>
172  * <li>0.1.2 Messages, exceptions and format.</li>
173  * <li>0.1.3 Starting and ending node as constants.</li>
174  * <li>0.1.4 Variable names and final.</li>
175  * <li>1.0.0 Moved to version 1.</li>
176  * <li>1.1.0 Delimiters as part of the grammar.</li>
177  * <li>1.2.0 Exception hierarchy changed.</li>
178  * <li>1.2.1 Log modified.</li>
179  * <li>1.3.0 Extends a class.</li>
180  * <li>1.3.1 Strings externalized.</li>
181  * <li>1.3.2 XML names as constants.</li>
182  * <li>1.4.0 Assert, throws and constants names.</li>
183  * <li>1.4.1 Assert, signature and null validation.</li>
184  * <li>1.4.2 compareTo -> equals.</li>
185  * <li>1.5.0 Check graph and addParent.</li>
186  * <li>1.5.1 GraphToken renamed by GraphNode</li>
187  * <li>1.6.0 GrammarReader separated from Graph.</li>
188  * <li>1.7.0 Reading grammar for different files.</li>
189  * <li>1.7.1 Validation with XML Schema. Delimiters is an attribute.</li>
190  * <li>1.7.2 Validation in an independent stream and method.</li>
191  * <li>1.8.0 New structure.</li>
192  * <li>1.9.0 Return graph.</li>
193  * <li>1.10.0 Protected attributes -> private.</li>
194  * <li>1.10.1 Extra nodes from configuration.</li>
195  * </ul>
196  *
197  * @author Andres Gomez Casanova <a
198  *         href="mailto:a n g o c a at y a h o o dot c o m" >(AngocA)</a>
199  * @version 1.10.1 2010-08-08
200  */
201 public final class ImplementationXMLGrammarReader extends
202 		AbstractTwoPhaseGrammarReader {
203 
204 	/**
205 	 * Grammar delimiters.
206 	 */
207 	private static final String DELIMITERS = "delimiters"; //$NON-NLS-1$
208 
209 	/**
210 	 * Logger.
211 	 */
212 	private static final Logger LOGGER = LoggerFactory
213 			.getLogger(ImplementationXMLGrammarReader.class);
214 
215 	/**
216 	 * Token's id.
217 	 */
218 	private static final String NODE_ID = "id"; //$NON-NLS-1$
219 	/**
220 	 * Token's name.
221 	 */
222 	private static final String NODE_NAME = "name"; //$NON-NLS-1$
223 	/**
224 	 * Token.
225 	 */
226 	private static final String TOKEN = "token"; //$NON-NLS-1$
227 	/**
228 	 * Token's children.
229 	 */
230 	private static final String TOKEN_ID_TOKEN = "idToken"; //$NON-NLS-1$
231 
232 	/**
233 	 * Token represents a reserved word.
234 	 */
235 	private static final String TOKEN_RESERVED = "reserved"; //$NON-NLS-1$
236 	/**
237 	 * Value of the property to validate the grammar file.
238 	 */
239 	private static final String TRUE = "true";
240 	/**
241 	 * Property to validate the grammar file.
242 	 */
243 	private static final String VALIDATE_GRAMMAR_PROPERTY = "ValidateGrammar";
244 
245 	/**
246 	 * Read the grammar file.
247 	 *
248 	 * @param fileName
249 	 *            Name of the xml file.
250 	 * @return The xml file ready to be processed.
251 	 * @throws AbstractGrammarFileReaderException
252 	 *             When there is a problem opening the file.
253 	 */
254 	private static InputSource/* ! */readSource(final String/* ! */fileName)
255 			throws AbstractGrammarReaderException,
256 			AbstractGrammarFileReaderException {
257 		if (fileName == null) {
258 			throw new GrammarFileNotDefinedException();
259 		}
260 
261 		InputStream inputStream = null;
262 		try {
263 			inputStream = FileReader.getStream(fileName);
264 		} catch (final AbstractZemucanException e) {
265 			throw new GeneralGrammarFileProblemException(e);
266 		}
267 		final InputSource content = new InputSource(inputStream);
268 
269 		assert content != null;
270 		return content;
271 	}
272 
273 	/**
274 	 * Content to parse.
275 	 */
276 	private InputSource contentToParse;
277 
278 	/**
279 	 * Content to validate.
280 	 */
281 	private InputSource contentToValidate;
282 
283 	/**
284 	 * Document structure.
285 	 */
286 	private Document dom;
287 	/**
288 	 * Graph that represents the grammar.
289 	 */
290 	private Graph graph;
291 
292 	/**
293 	 * Default constructor that fill the given graph with the grammar content.
294 	 *
295 	 * @param graphToFill
296 	 *            Graph to fill with the grammar content.
297 	 * @param contentToBeParsed
298 	 *            Data from the grammar file to parse. This stream is open.
299 	 * @param contentToBeValidated
300 	 *            Data from the grammar file to validate. This stream is open.
301 	 * @throws AbstractZemucanException
302 	 *             When there is a problem reading the grammar file or building
303 	 *             the graph. If there is a null parameter. When there is a
304 	 *             problem with the delimiters.
305 	 */
306 	ImplementationXMLGrammarReader(final Graph/* ! */graphToFill,
307 			final InputSource/* ! */contentToBeParsed,
308 			final InputSource/* ! */contentToBeValidated)
309 			throws AbstractZemucanException {
310 		super();
311 
312 		if (contentToBeParsed == null) {
313 			throw new ParameterNullException("contentToParse"); //$NON-NLS-1$
314 		}
315 		if (contentToBeValidated == null) {
316 			throw new ParameterNullException("contentToValidate"); //$NON-NLS-1$
317 		}
318 		if (graphToFill == null) {
319 			throw new ParameterNullException("graph"); //$NON-NLS-1$
320 		}
321 		ImplementationXMLGrammarReader.LOGGER
322 				.debug("Creating the grammar reader"); //$NON-NLS-1$
323 
324 		this.contentToParse = contentToBeParsed;
325 		this.contentToValidate = contentToBeValidated;
326 		this.graph = graphToFill;
327 		this.dom = null;
328 	}
329 
330 	/**
331 	 * Public constructor that reads the grammar from a file.
332 	 *
333 	 * @param graphToFill
334 	 *            Graph where the read nodes are placed.
335 	 * @param fileName
336 	 *            Name of the file that contains the grammar.
337 	 * @throws AbstractZemucanException
338 	 *             If the grammar file defined in the configuration file is not
339 	 *             found. If the graph that represents the grammar is invalid.
340 	 *             If a parameter is null. If there is a problem reading the
341 	 *             grammar.
342 	 */
343 	public ImplementationXMLGrammarReader(final Graph/* ! */graphToFill,
344 			final String/* ! */fileName) throws AbstractZemucanException {
345 		super();
346 
347 		if (graphToFill == null) {
348 			throw new ParameterNullException("graphToFill"); //$NON-NLS-1$
349 		}
350 		if (fileName == null) {
351 			throw new ParameterNullException("fileDescriptor"); //$NON-NLS-1$
352 		}
353 
354 		this.graph = graphToFill;
355 		this.fileDescriptor = fileName;
356 		this.contentToParse = null;
357 		this.contentToValidate = null;
358 		this.dom = null;
359 	}
360 
361 	/**
362 	 * Reads the document and creates all the nodes.
363 	 * <p>
364 	 * NOTE: This phase does not create the relations between nodes.
365 	 *
366 	 * @throws AbstractZemucanException
367 	 *             When there are several nodes in the grammar file with the
368 	 *             same id, or when the name or the id of a node is invalid.
369 	 *             When the graph is inconsistent.
370 	 */
371 	protected final void firstPhase() throws AbstractZemucanException {
372 
373 		// Gets the root element.
374 		final Element docEle = this.dom.getDocumentElement();
375 
376 		// Gets the nodes.
377 		final NodeList nodelist = docEle
378 				.getElementsByTagName(ImplementationXMLGrammarReader.TOKEN);
379 
380 		final int size = nodelist.getLength();
381 		ImplementationXMLGrammarReader.LOGGER.debug(
382 				"Processing {} nodes", Integer.toString(size)); //$NON-NLS-1$
383 		if (size > 0) {
384 			for (int i = 0; i < size; i += 1) {
385 				// Gets the node element.
386 				final Element eleNode = (Element) nodelist.item(i);
387 
388 				// Adds the Node object.
389 				this.readAndAddNode(eleNode);
390 			}
391 		}
392 	}
393 
394 	/*
395 	 * (non-Javadoc)
396 	 *
397 	 * @see
398 	 * name.angoca.zemucan.grammarReader.api.AbstractGrammarReader#generateGraph
399 	 * ()
400 	 */
401 	@Override
402 	public Graph/* ! */generateGraph() throws AbstractZemucanException {
403 		if ((this.contentToParse == null) && (this.contentToValidate == null)) {
404 			final String[] files = this.getFileNamesFromDescriptor();
405 			// There is just one file in the descriptor.
406 			if (files.length <= 0) {
407 				this.contentToParse = ImplementationXMLGrammarReader
408 						.readSource(this.fileDescriptor);
409 				this.contentToValidate = ImplementationXMLGrammarReader
410 						.readSource(this.fileDescriptor);
411 			} else {
412 				// There are several files in the descriptor.
413 				final List<Graph> graphs = new ArrayList<Graph>(files.length);
414 				final List<String> delimiters = new ArrayList<String>(
415 						files.length);
416 				for (int i = 0; i < files.length; i++) {
417 					final String filename = files[i];
418 					final boolean extraNodes = !Boolean.parseBoolean(System
419 							.getProperty(Constants.WITHOUT_EXTRA_NODES));
420 					final Graph newGraph = new Graph(this.fileDescriptor + "/"
421 							+ filename, extraNodes);
422 					graphs.add(newGraph);
423 					final ImplementationXMLGrammarReader grammar = new ImplementationXMLGrammarReader(
424 							newGraph, this.fileDescriptor + File.separatorChar
425 									+ filename);
426 					grammar.generateGraph();
427 					grammar.getStartingNode();
428 					delimiters.add(grammar.getDelimiters());
429 				}
430 				this.graph = GrammarReaderController.mergeGraphs(graphs
431 						.toArray(new Graph[0]));
432 				super.setDelimiters(GrammarReaderController
433 						.processDelimiters(delimiters));
434 
435 			}
436 		}
437 		// There is not a defined descriptor, or the contents from file are
438 		// ready.
439 		if ((this.contentToParse != null) && (this.contentToValidate != null)) {
440 			// Validates the XML file.
441 			this.validation(this.contentToValidate);
442 
443 			// Parses the XML file and gets the DOM object.
444 			this.dom = this.parseXmlFile();
445 
446 			super.setStartingNode(this.readGraph());
447 
448 			super.setDelimiters(this.readDelimiters());
449 		}
450 		super.setGrammarProcessed(true);
451 		return this.graph;
452 	}
453 
454 	/**
455 	 * Retrieves the children of a node and put them in it. Takes the nodes read
456 	 * from the first phase and stored in the node class attribute.
457 	 *
458 	 * @param eleNode
459 	 *            Description of a node.
460 	 * @throws AbstractZemucanException
461 	 *             if there is a not existing node. Or if the child graph node
462 	 *             is null. Or if endingNode has children. If a parameter is
463 	 *             null.
464 	 */
465 	private void getChildren(final Element/* ! */eleNode)
466 			throws AbstractZemucanException {
467 		assert eleNode != null;
468 
469 		// For each node asks the id.
470 		final String nodeId = this.getTextValue(eleNode,
471 				ImplementationXMLGrammarReader.NODE_ID);
472 
473 		// Retrieves the node with that id.
474 		if (nodeId != null) {
475 			// Gets the children of that node.
476 			final NodeList childList = eleNode
477 					.getElementsByTagName(ImplementationXMLGrammarReader.TOKEN_ID_TOKEN);
478 
479 			final int size = childList.getLength();
480 			if (size > 0) {
481 				for (int i = 0; i < size; i += 1) {
482 					// Gets the child node element.
483 					final Element childElement = (Element) childList.item(i);
484 
485 					// Establishes the children of a GraphNode object.
486 					final String childId = childElement.getFirstChild()
487 							.getNodeValue();
488 
489 					// Creates the association parent - child.
490 					this.graph.addRelation(nodeId, childId);
491 				}
492 			}
493 		}
494 	}
495 
496 	/**
497 	 * It takes an XML element and the tag name, then it looks for the tag and
498 	 * gets the text content.
499 	 *
500 	 * @param element
501 	 *            XML element to read.
502 	 * @param tagName
503 	 *            Name of the element.
504 	 * @return Content of the element with the given name.
505 	 */
506 	private String/* ? */getTextValue(final Element/* ! */element,
507 			final String/* ! */tagName) {
508 		assert element != null;
509 		assert tagName != null;
510 
511 		String textValue = null;
512 		final NodeList nodelist = element.getElementsByTagName(tagName);
513 		if (nodelist.getLength() > 0) {
514 			final Element elem = (Element) nodelist.item(0);
515 			textValue = elem.getFirstChild().getNodeValue();
516 		}
517 
518 		return textValue;
519 	}
520 
521 	/**
522 	 * Loads the document builder.
523 	 *
524 	 * @return The DOM read from the file.
525 	 * @throws AbstractGrammarFileReaderException
526 	 *             If there is a problem reading the XML file that contains the
527 	 *             grammar.
528 	 */
529 	private Document/* ! */parseXmlFile()
530 			throws AbstractGrammarFileReaderException {
531 		assert this.contentToParse != null;
532 
533 		ImplementationXMLGrammarReader.LOGGER.debug("Parsing the XML file"); //$NON-NLS-1$
534 
535 		DocumentBuilder parser = null;
536 		Document document = null;
537 
538 		// Using factory, gets an instance of document builder.
539 		try {
540 			parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
541 			// Sets the error Handle of the XML reader.
542 			parser.setErrorHandler(new Handler());
543 			// Parse using builder to get DOM representation of the XML file.
544 			document = parser.parse(this.contentToParse);
545 		} catch (final ParserConfigurationException e) {
546 			// I don't know how to test this part. It's outside my scope.
547 			throw new XMLProblemException(e);
548 		} catch (final SAXException exception) {
549 			throw new XMLProblemException(exception);
550 		} catch (final IOException exception) {
551 			// I don't know how to test this part. It's outside my scope.
552 			throw new GeneralGrammarFileProblemException(exception);
553 		}
554 
555 		assert document != null;
556 		return document;
557 	}
558 
559 	/**
560 	 * It takes a node element and reads the values in it, then creates a graph
561 	 * node object and returns it.
562 	 *
563 	 * @param eleNode
564 	 *            element where the data of the node can be found.
565 	 * @throws AbstractZemucanException
566 	 *             The name is invalid, or the id. When the graph is
567 	 *             inconsistent.
568 	 */
569 	private void readAndAddNode(final Element/* ! */eleNode)
570 			throws AbstractZemucanException {
571 		assert eleNode != null;
572 
573 		// For each node asks the id, name and if it is reserved.
574 		final String nodeId = this.getTextValue(eleNode,
575 				ImplementationXMLGrammarReader.NODE_ID);
576 		final String name = this.getTextValue(eleNode,
577 				ImplementationXMLGrammarReader.NODE_NAME);
578 		final NodeList nodelist = eleNode
579 				.getElementsByTagName(ImplementationXMLGrammarReader.TOKEN_RESERVED);
580 		boolean reserved = false;
581 		if (nodelist.getLength() > 0) {
582 			reserved = true;
583 		}
584 		if (nodeId == null) {
585 			if (name == null) {
586 				throw new NoIdNoNameDefinedInNodeException();
587 			}
588 			// The grammar does not define an id.
589 			throw new NoIdDefinedInNodeException(name);
590 		} else if (name == null) {
591 			// The grammar does not define a name.
592 			throw new NoNameDefinedInNodeException(nodeId);
593 		}
594 		this.graph.addNode(nodeId, name, reserved);
595 	}
596 
597 	/**
598 	 * Reads the delimiters of the grammar.
599 	 *
600 	 * @param dom
601 	 *            XML file parsed.
602 	 * @return The delimiters that separates the tokens.
603 	 * @throws DelimitersIncorrectlyDefinedException
604 	 *             When the grammar has not defined the delimiters.
605 	 */
606 	private String/* ! */readDelimiters()
607 			throws DelimitersIncorrectlyDefinedException {
608 		ImplementationXMLGrammarReader.LOGGER.debug("Reading the delimiters"); //$NON-NLS-1$
609 
610 		String delimitersRead = null;
611 		// Gets the root element.
612 		final Element docEle = this.dom.getDocumentElement();
613 
614 		// Gets the delimiters
615 		final Attr attributes = docEle
616 				.getAttributeNode(ImplementationXMLGrammarReader.DELIMITERS);
617 
618 		try {
619 			delimitersRead = attributes.getValue();
620 		} catch (final NullPointerException exception) {
621 			throw new DelimitersIncorrectlyDefinedException();
622 		}
623 		if ((delimitersRead == null) || delimitersRead.equals("")) {
624 			throw new DelimitersIncorrectlyDefinedException();
625 		}
626 
627 		assert delimitersRead != null;
628 		return delimitersRead;
629 	}
630 
631 	/**
632 	 * Reads the graph and return the entry point that is the starting node.
633 	 *
634 	 * @return The startingNode that is the entry point of the graph.
635 	 * @throws AbstractZemucanException
636 	 *             If the grammar is invalid. If the graph becomes invalid. If a
637 	 *             parameter is null.
638 	 */
639 	private StartingNode/* ! */readGraph() throws AbstractZemucanException {
640 
641 		// Gets each node element without relations.
642 		this.firstPhase();
643 
644 		this.graph.firstPhaseFinished();
645 
646 		// Creates the relations between nodes.
647 		this.secondPhase();
648 
649 		final StartingNode node = this.graph.secondPhaseFinished();
650 
651 		assert node != null;
652 		return node;
653 	}
654 
655 	/**
656 	 * Creates the relations between nodes.
657 	 *
658 	 * @throws AbstractZemucanException
659 	 *             when there is a not existing node. Or if the child graph node
660 	 *             is null. Or if endingNode has children. If a parameter is
661 	 *             null.
662 	 */
663 	protected final void secondPhase() throws AbstractZemucanException {
664 
665 		// Gets the root element.
666 		final Element docEle = this.dom.getDocumentElement();
667 
668 		// Gets the Nodes
669 		final NodeList nodeList = docEle
670 				.getElementsByTagName(ImplementationXMLGrammarReader.TOKEN);
671 
672 		// Iterates over the set of nodes that represents tokens in
673 		// the grammar.
674 		final int size = nodeList.getLength();
675 		if (size > 0) {
676 			for (int i = 0; i < size; i += 1) {
677 
678 				// Gets the node element.
679 				final Element eleNode = (Element) nodeList.item(i);
680 
681 				// Establishes the children of a Node object.
682 				this.getChildren(eleNode);
683 			}
684 		}
685 	}
686 
687 	/**
688 	 * Validates the xml file.
689 	 *
690 	 * @param input
691 	 *            Content of the XML file.
692 	 * @throws GeneralGrammarFileProblemException
693 	 *             IO Exception.
694 	 * @throws GrammarFileNotFoundException
695 	 *             If the file is not found.
696 	 * @throws XMLProblemException
697 	 *             If there is a problem parsing the file.
698 	 * @throws GrammarFileNotDefinedException
699 	 *             If the file is not defined.
700 	 */
701 	private void validation(final InputSource input)
702 			throws GeneralGrammarFileProblemException, XMLProblemException,
703 			GrammarFileNotDefinedException {
704 		final String validate = Configurator.getInstance().getProperty(
705 				ImplementationXMLGrammarReader.VALIDATE_GRAMMAR_PROPERTY);
706 		if ((validate != null)
707 				&& validate.equals(ImplementationXMLGrammarReader.TRUE)) {
708 			Schema schema = null;
709 
710 			// Creates the validator
711 			final SchemaFactory schemaFactory = SchemaFactory
712 					.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
713 			StreamSource schemaSource;
714 			try {
715 				schemaSource = new StreamSource(
716 						FileReader.getStream("grammar.xsd"));
717 			} catch (final AbstractZemucanException e) {
718 				throw new GeneralGrammarFileProblemException(e);
719 			}
720 			try {
721 				schema = schemaFactory.newSchema(schemaSource);
722 			} catch (final SAXException exception) {
723 				throw new XMLProblemException(exception);
724 			}
725 
726 			final Validator validator = schema.newValidator();
727 			validator.setErrorHandler(new Handler());
728 
729 			// Validates the document.
730 			// TODO v1.1 Validar la version del XML Schema
731 			final Source source = new StreamSource(input.getByteStream());
732 			try {
733 				validator.validate(source);
734 			} catch (final SAXException exception) {
735 				throw new XMLProblemException(exception);
736 			} catch (final IOException exception) {
737 				// I don't know how to test this part. It's outside my scope.
738 				throw new GeneralGrammarFileProblemException(exception);
739 			}
740 		}
741 	}
742 }