/*
* Copyright (c) 2011, 2013. iCarto
*
* This file is part of extNavTableForms
*
* extNavTableForms 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 any later version.
*
* extNavTableForms 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 extNavTableForms.
* If not, see <http://www.gnu.org/licenses/>.
*/
package es.icarto.gvsig.navtableforms.ormlite;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
import es.icarto.gvsig.navtableforms.ormlite.domainvalidator.DomainRulesFactory;
import es.icarto.gvsig.navtableforms.ormlite.domainvalidator.ValidatorDomain;
import es.icarto.gvsig.navtableforms.ormlite.domainvalidator.rules.ValidationRule;
import es.icarto.gvsig.navtableforms.ormlite.domainvalues.DomainReader;
import es.icarto.gvsig.navtableforms.ormlite.domainvalues.DomainReaderDB;
import es.icarto.gvsig.navtableforms.ormlite.domainvalues.DomainReaderFile;
import es.icarto.gvsig.navtableforms.ormlite.widgetsdependency.DependencyReader;
/**
* SAX parser to build from a XML structure several objects needed for
* validation.
*
* @author Andr�s Maneiro <amaneiro@icarto.es>
* @author Jorge L�pez <jlopez@cartolab.es>
* @author Pablo Sanxiao <psanxiao@icarto.es>
* @author Franciscoo Puga <fpuga@icarto.es>
*
*/
public class XMLSAXParser extends DefaultHandler {
// TODO check where gvSIG do that and take values from there
static final String GVSIG_DEFAULT_STRING = "";
static final int GVSIG_DEFAULT_INT = 0;
static final double GVSIG_DEFAULT_DOUBLE = 0.0;
static final boolean GVSIG_DEFAULT_BOOLEAN = false;
private String xmlFile = null;
private ORMLiteAppDomain ad = null;
private String tmpVal = null;
private DomainReader tmpDomainReader = null;
private FieldDescription tmpFieldDescription = null;
private DependencyReader tmpDependencyReader = null;
private String latestDpnComponent, latestDpnValue;
private static Logger logger = Logger.getLogger("SAX Parser");
public XMLSAXParser(String xmlFile) throws ParserConfigurationException,
SAXException, IOException {
setXMLFile(xmlFile);
setAD(new ORMLiteAppDomain());
parseDocument();
}
private String getXMLFile() {
return xmlFile;
}
private String getXMLFileDir() {
return new File(xmlFile).getParent() + File.separator;
}
private void setXMLFile(String xmlFile) {
this.xmlFile = xmlFile;
}
public ORMLiteAppDomain getAD() {
return ad;
}
public void setAD(ORMLiteAppDomain ad) {
this.ad = ad;
}
private void parseDocument() throws ParserConfigurationException,
SAXException, IOException {
// get a factory
SAXParserFactory spf = SAXParserFactory.newInstance();
// get a new instance of parser
SAXParser sp = spf.newSAXParser();
// parse the file and also register this class for call backs
sp.parse(getXMLFile(), this);
}
// Event Handlers
/**
* Callback called every time SAX parser gets a new tag. ie: " < field > "
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// reset
tmpVal = "";
if (qName.equalsIgnoreCase("FIELD")) {
// set field
tmpFieldDescription = new FieldDescription();
}
else if (qName.equalsIgnoreCase("ENABLEIF")) {
tmpDependencyReader = new DependencyReader();
}
else if (qName.equalsIgnoreCase("CONDITION")) {
latestDpnComponent = null;
latestDpnValue = null;
}
}
/**
* Callback called every time SAX parser gets text (spaces, text between
* tags, ...).
*
* SAX parsers may return all contiguous character data in a single chunk,
* or they may split it into several chunks. See:
* http://download.oracle.com/javase/1.5.0/docs/api/org/xml/sax/
* ContentHandler.html#characters%28char%5b%5d,%20int,%20int%29
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
tmpVal = tmpVal + new String(ch, start, length);
}
/**
* Callback called every time SAX parser gets a end tag like "< / field >"
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// set tmp field structure
if (qName.equalsIgnoreCase("FIELDNAME")) {
tmpFieldDescription.setFieldName(tmpVal);
}
else if (qName.equalsIgnoreCase("DRTYPE")) {
if (tmpVal.equalsIgnoreCase("DB")) {
tmpDomainReader = new DomainReaderDB();
} else if (tmpVal.equalsIgnoreCase("FILE")) {
tmpDomainReader = new DomainReaderFile();
}
}
// set tmp domain db reader configuration
else if (qName.equalsIgnoreCase("DRDBTABLE")) {
if (tmpDomainReader instanceof DomainReaderDB) {
((DomainReaderDB) tmpDomainReader).setTable(tmpVal);
}
} else if (qName.equalsIgnoreCase("DRDBSCHEMA")) {
if (tmpDomainReader instanceof DomainReaderDB) {
((DomainReaderDB) tmpDomainReader).setSchema(tmpVal);
}
} else if (qName.equalsIgnoreCase("DRDBCOLUMNALIAS")) {
if (tmpDomainReader instanceof DomainReaderDB) {
((DomainReaderDB) tmpDomainReader).setColumnAlias(tmpVal);
}
} else if (qName.equalsIgnoreCase("DRDBCOLUMNVALUE")) {
if (tmpDomainReader instanceof DomainReaderDB) {
((DomainReaderDB) tmpDomainReader).setColumnValue(tmpVal);
}
} else if (qName.equalsIgnoreCase("DRDBFOREIGNKEY")) {
if (tmpDomainReader instanceof DomainReaderDB) {
((DomainReaderDB) tmpDomainReader).addColumnForeignKey(tmpVal);
}
} else if (qName.equalsIgnoreCase("DRADDVOIDVALUE")) {
tmpDomainReader.setAddVoidValue(Boolean.parseBoolean(tmpVal));
}
// set tmp domain file reader configuration
else if (qName.equalsIgnoreCase("DRFILENAME")) {
if (tmpDomainReader instanceof DomainReaderFile) {
((DomainReaderFile) tmpDomainReader).setFileName(this
.getXMLFileDir() + tmpVal);
}
} else if (qName.equalsIgnoreCase("DRFILEFIELDALIAS")) {
if (tmpDomainReader instanceof DomainReaderFile) {
((DomainReaderFile) tmpDomainReader).setFieldAlias(tmpVal);
}
}
// save validation rule for the field
else if (qName.equalsIgnoreCase("VALIDATIONRULE")) {
ValidationRule rule = DomainRulesFactory.createRule(tmpVal);
if (rule != null) {
if (getAD().getDomainValidatorForComponent(
tmpFieldDescription.getFieldName()) == null) {
getAD().addDomainValidator(
tmpFieldDescription.getFieldName(),
new ValidatorDomain(null));
}
getAD().getDomainValidatorForComponent(
tmpFieldDescription.getFieldName()).addRule(rule);
}
}
// save tmp values of DomainReader in AplicationDomain
else if (qName.equalsIgnoreCase("DOMAINREADER")) {
getAD().addDomainValues(tmpFieldDescription.getFieldName(),
tmpDomainReader.getDomainValues());
}
// save tmp values of widgets dependency
else if (qName.equalsIgnoreCase("COMPONENT")) {
latestDpnComponent = tmpVal;
}
else if (qName.equalsIgnoreCase("VALUE")) {
latestDpnValue = tmpVal;
}
else if (qName.equalsIgnoreCase("CONDITION")) {
if ((latestDpnValue != null) && (latestDpnComponent != null)) {
tmpDependencyReader.addCondition(latestDpnComponent,
latestDpnValue);
}
}
// save tmp values of DependencyReader in ApplicationDomain
else if (qName.equalsIgnoreCase("ENABLEIF")) {
getAD().addDependencyValues(tmpFieldDescription.getFieldName(),
tmpDependencyReader);
}
else if (qName.equalsIgnoreCase("NONEDITABLE")) {
getAD().addNonEditableComponent(tmpFieldDescription.getFieldName(),
true);
}
}
}