package org.xmlcml.cif;

import nu.xom.Document;

/**
 * Receive notification of the logical content of a document.
 * 
 * <p>
 * Heavily modelled on SAXContentHandler.
 * </p>
 * 
 * <p>
 * This is the main interface that most SAX applications implement: if the
 * application needs to be informed of basic parsing events, it implements this
 * interface and registers an instance with the SAX parser using the
 * setContentHandler method. The parser uses the instance to report basic
 * document-related events like the start and end of elements and character
 * data.
 * </p>
 * <p>
 * The order of events in this interface is very important, and mirrors the
 * order of information in the document itself. For example, all of an element's
 * content (character data, processing instructions, and/or subelements) will
 * appear, in order, between the startElement event and the corresponding
 * endElement event.
 * </p>
 * <p>
 * 
 * This interface is similar to the now-deprecated SAX 1.0 DocumentHandler
 * interface, but it adds support for Namespaces and for reporting skipped
 * entities (in non-validating XML processors).
 * </p>
 * <p>
 * NOTE: This design is closely modelled on the SAX design for XML (Megginson,
 * Murray-Rust, Bray and many others, http://sax.sf.net) and re-uses much of the
 * material (special thanks to David Megginson).
 * </p>
 * <p>
 * CIF applications programmers may use CIFContentHandler as follows:
 * 
 * <pre>
 </pre>
 * 
 * </p>
 */

public interface CIFContentHandler extends CIFConstants {

	/**
	 * checks for duplicate loops and items
	 * 
	 * @param checkDuplicates
	 *            if true and if duplicates occur will throw exception
	 */
	void setCheckDuplicates(boolean checkDuplicates);

	/**
	 * Receive an object for locating the origin of SAX document events. SAX
	 * parsers are strongly encouraged (though not absolutely required) to
	 * supply a locator: if it does so, it must supply the locator to the
	 * application by invoking this method before invoking any of the other
	 * methods in the ContentHandler interface. The locator allows the
	 * application to determine the end position of any document-related event,
	 * even if the parser is not reporting an error. Typically, the application
	 * will use this information for reporting its own errors (such as character
	 * content that does not match an application's business rules). The
	 * information returned by the locator is probably not sufficient for use
	 * with a search engine. Note that the locator will return correct
	 * information only during the invocation of the events in this interface.
	 * The application should not attempt to use it at any other time.
	 * Parameters: locator - An object that can return the location of any SAX
	 * document event. See Also: Locator
	 * 
	 * @param locator
	 */
	void setLocator(CIFLocator locator);

	/**
	 * Receive notification of the beginning of a document.
	 * 
	 * The CIF parser will invoke this method only once, before any other
	 * methods in this interface (except for setDocumentLocator). it creates a
	 * rootElements and wraps it in a Document which it returns
	 * 
	 * @see #endDocument()
	 * @throws CIFException
	 * @return some handlers return a new document, else null
	 */
	Document startDocument() throws CIFException;

	/**
	 * Receive notification of the end of a document.
	 * 
	 * <p>
	 * The SAX parser will invoke this method only once, and it will be the last
	 * method invoked during the parse. The parser shall not invoke this method
	 * until it has either abandoned parsing (because of an unrecoverable error)
	 * or reached the end of input.
	 * </p>
	 * 
	 * @see #startDocument()
	 * @throws CIFException
	 */
	void endDocument() throws CIFException;

	/**
	 * Receive notification of the beginning of a data block.
	 * 
	 * <p>
	 * The Parser will invoke this method at the beginning of every dataBlock
	 * (data_foo) in the CIF document. CIF contains no explicit endDataBlock
	 * event, but this must be explicitly generated by a CIF parser (even when
	 * the dataBlock is empty). All of the dataBlock's content will be reported,
	 * in order, before the corresponding endDataBlock event.
	 * </p>
	 * 
	 * @param id
	 *            the id of the dataBlock
	 * @throws CIFException
	 *             dataBlock has no id
	 */
	CIFDataBlock startDataBlock(String id) throws CIFException;

	/**
	 * Receive notification of addition of a CIFItem.
	 * 
	 * <p>
	 * The Parser will invoke this method at the end of every item (tag+data) in
	 * the CIF document. CIF contains no explicit endItem event, and addItem
	 * must be explicitly generated by a CIF parser
	 * </p>
	 * 
	 * @param item
	 *            to add
     * @return message
	 * @throws CIFException
	 */
	ParserMessage addItem(CIFItem item) throws CIFException;

	/**
	 * Receive notification of a CIFLoop.
	 * 
	 * <p>
	 * The Parser will invoke this method at the end of every loop (loop_ +
	 * names + values) in the CIF document.
	 * </p>
	 * 
	 * @param loop
	 *            to add
	 * @throws CIFException
	 *             bad shape of loop, and several others
	 */
	void addLoop(CIFLoop loop) throws CIFException;

	/**
	 * Receive notification of ignorable whitespace between other elements.
	 * 
	 * CIFSAX parsers may return all contiguous whitespace in a single chunk, or
	 * they may split it into several chunks
	 * 
	 * @param s
	 *            the whitespace
	 * @throws CIFException -
	 *             Any CIF exception, possibly wrapping another exception.
	 */
	void addWhitespace(String s) throws CIFException;

	/**
	 * Receive notification of a fullline comment or block of comments.
	 * 
	 * <p>
	 * Comments are for humans to read in documents and dictionaries and
	 * strictly are not part of the data. Users should not rely on comment data
	 * being passed through CIFDOM. However since comments sometimes contain
	 * critical identification or intellectual property info we provide a
	 * mechanism for passing them. Note that the <b>position of comments has no
	 * clear semantics.</b> The order of comments and their chunking is
	 * preserved but not their relation to other elements.
	 * </p>
	 * <p>
	 * Comments can occur in the following places:
	 * <ul>
	 * <li>within a line (up to end)</li>
	 * <li>Before the first dataBlock</li>
	 * <li>between data items</li>
	 * </ul>
	 * Inline comments are restricted to a single String and this can be used to
	 * identify them. Other comments often occur in blocks and we use the
	 * convention that all contiguous comments are part of a single commonBlock.
	 * No blank lines are allowed in such a block; they split it into separate
	 * blocks.
	 * </p>
	 * 
	 * @param data
	 *            the comment values (without leading #). All comments are
	 *            right-trimmed
	 * @throws CIFException -
	 *             Any CIFException, possibly wrapping another exception.
	 * @see #comment
	 */
	void comments(String[] data) throws CIFException;

	/**
	 * Receive notification of an inline comment.
	 * <p>
	 * Comments are for humans to read in documents and dictionaries and
	 * strictly are not part of the data. Users should not rely on comment data
	 * being passed through CIFDOM. However since comments sometimes contain
	 * critical identification or intellectual property info we provide a
	 * mechanism for passing them. Note that the <b>position of comments has no
	 * clear semantics.</b> The order of comments and their chunking is
	 * preserved but not their relation to other elements.
	 * </p>
	 * <p>
	 * Comments can occur in the following places:
	 * <ul>
	 * <li>within a line (up to end)</li>
	 * <li>Before the first dataBlock</li>
	 * <li>between data items</li>
	 * </ul>
	 * Inline comments are restricted to a single String and this can be used to
	 * identify them. Other comments often occur in blocks and we use the
	 * convention that all contiguous comments are part of a single commonBlock.
	 * No blank lines are allowed in such a block; they split it into separate
	 * blocks.
	 * </p>
	 * 
	 * @param data
	 *            the comment values (without leading #). All comments are
	 *            right-trimmed
	 * @throws CIFException -
	 *             Any CIFException, possibly wrapping another exception.
	 * @see #comments
	 */
	void comment(String data) throws CIFException;

}
