com.datastax.data.dataset.io.schema.XMLDataSetSchemaReader Maven / Gradle / Ivy
package com.datastax.data.dataset.io.schema;
import com.datastax.data.dataset.*;
import com.datastax.data.dataset.provider.sql.SQLCommand;
import com.datastax.data.dataset.provider.sql.SQLDataProvider;
import com.datastax.data.dataset.provider.sql.TableCommand;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class XMLDataSetSchemaReader implements DataSetSchemaReader {
private String xmlContents;
private DataSetParser lastParserUsed;
public XMLDataSetSchemaReader(InputStream xmlInputStream) throws SchemaReaderException {
this(new InputStreamReader(xmlInputStream));
}
public XMLDataSetSchemaReader(Reader xmlReader) throws SchemaReaderException {
String xml = "";
if ( ! ( xmlReader instanceof BufferedReader)) {
xmlReader = new BufferedReader(xmlReader);
}
try {
StringBuilder builder = new StringBuilder();
char[] bytes = new char[4096];
int length = -1;
while ((length = xmlReader.read(bytes)) != -1) {
builder.append(new String(bytes, 0, length));
}
this.xmlContents = builder.toString();
} catch (Exception e) {
throw new SchemaReaderException("Can't read input stream to parse schema from.", e);
}
}
public DataSet readDataSet() throws SchemaReaderException {
return readXml(new DataSet());
}
public DataSet readDataSet(String... tableNames) throws SchemaReaderException {
return readXml(new DataSet(), tableNames);
}
public List addRelations(DataSet dataSet, String... tableNames) throws SchemaReaderException {
readXml(dataSet, tableNames);
return lastParserUsed.getRelationsAdded();
}
public List addTables(DataSet dataSet, String... tableNames) throws SchemaReaderException {
readXml(dataSet, tableNames);
return lastParserUsed.getTablesAdded();
}
private DataSet readXml(DataSet dataSet, String... tableNames) throws SchemaReaderException {
try {
SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
InputSource is = new InputSource(new StringReader(xmlContents));
lastParserUsed = new DataSetParser(dataSet, tableNames);
parser.parse(is, lastParserUsed);
} catch (Exception e) {
throw new SchemaReaderException("Failed to setup schema XML parser.", e);
}
return dataSet;
}
private static final class DataSetParser extends DefaultHandler {
public int elementDepth = 0;
private Attributes attrs;
private DataSet ds;
private DataTable table;
private DataColumn column;
private DataProvider dataProvider;
private List tableNames;
private List tablesAdded;
private List relationsAdded;
public DataSetParser(DataSet ds, String... tableNames) {
this.ds = ds == null ? new DataSet() : ds;
this.tableNames = new ArrayList(tableNames.length);
Collections.addAll(this.tableNames, tableNames);
}
public DataSet getDataSet() {
return ds;
}
public void startDocument() throws SAXException {
super.startDocument();
this.tablesAdded = new ArrayList();
this.relationsAdded = new ArrayList();
}
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
this.attrs = atts;
if (qName.equals("xs:element")) {
elementDepth++;
switch(elementDepth) {
case 1:
ds.setName(attrs.getValue("name"));
break;
case 2:
String tableName = attrs.getValue("name");
if ( ds.getTable(tableName) != null ) {
System.out.println("TABLE " + tableName + " ALREADY IN DATASET; SKIPPING.");
table = null;
break;
}
if ( tableNames.size() > 0 && !tableNames.contains(tableName)) {
table = null;
break;
}
table = ds.createTable(tableName);
String val = attrs.getValue("appendRowSupported");
table.setAppendRowSupported(val == null || val.equalsIgnoreCase("true"));
val = attrs.getValue("deleteRowSupported");
table.setDeleteRowSupported(val == null || val.equalsIgnoreCase("true"));
tablesAdded.add(tableName);
break;
case 3:
if ( table == null ) break;
column = table.createColumn(attrs.getValue("name"));
val = attrs.getValue("minOccurs");
if (val != null && val.equals("")) {
column.setRequired(true);
}
val = attrs.getValue("keyColumn");
column.setKeyColumn(val == null ? false : val.equalsIgnoreCase("true"));
val = attrs.getValue("readOnly");
column.setReadOnly(val == null ? false : val.equalsIgnoreCase("true"));
String defaultValue = attrs.getValue("default");
val = attrs.getValue("type");
if (val.equals("xs:string")) {
column.setType(String.class);
if (defaultValue != null && !defaultValue.equals("")) {
column.setDefaultValue(defaultValue);
}
} else if (val.equals("xs:decimal")) {
column.setType(BigDecimal.class);
if (defaultValue != null && !defaultValue.equals("")) {
column.setDefaultValue(new BigDecimal(defaultValue));
}
} else if (val.equals("xs:integer") || val.equals("xs:int")) {
column.setType(Integer.class);
if (defaultValue != null && !defaultValue.equals("")) {
column.setDefaultValue(new Integer(defaultValue));
}
} else if (val.equals("xs:boolean")) {
column.setType(Boolean.class);
if (defaultValue != null && !defaultValue.equals("")) {
column.setDefaultValue(Boolean.parseBoolean(defaultValue));
}
} else if (val.equals("xs:date") || val.equals("xs:time") || val.equals("xs:dateTime")) {
column.setType(Date.class);
if (defaultValue != null && !defaultValue.equals("")) {
column.setDefaultValue(new Date(Date.parse(defaultValue)));
}
} else if (val.equals("xs:unsignedByte")) {
column.setType(Byte.class);
if (defaultValue != null && !defaultValue.equals("")) {
column.setDefaultValue(new Byte(defaultValue));
}
} else {
System.err.println("unexpected classType: '" + val + "'");
}
val = attrs.getValue("expression");
if (val != null && !("".equals(val))) {
column.setExpression(val);
}
break;
default:
System.out.println("Error in DataSetParser");
}
} else if (qName.equals("dataProvider")) {
String classType = attrs.getValue("class");
if (classType != null) {
try {
dataProvider = (DataProvider) Class.forName(classType).newInstance();
table.setDataProvider(dataProvider);
if (dataProvider instanceof SQLDataProvider) {
String tableName = attrs.getValue("tableName");
if (tableName != null && !tableName.equals("")) {
TableCommand cmd = new TableCommand(tableName);
cmd.setWhereClause(attrs.getValue("whereClause"));
cmd.setOrderByClause(attrs.getValue("orderByClause"));
cmd.setHavingClause(attrs.getValue("havingClause"));
dataProvider.setCommand(cmd);
} else {
SQLCommand command = new SQLCommand();
command.setSelectSQL(attrs.getValue("select"));
command.setInsertSQL(attrs.getValue("insert"));
command.setUpdateSQL(attrs.getValue("update"));
command.setDeleteSQL(attrs.getValue("delete"));
dataProvider.setCommand(command);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} else if (qName.equals("dataRelationTable")) {
DataRelationTable drt = ds.createRelationTable(attrs.getValue("name"));
drt.setRelation((DataRelation)ds.getElement(attrs.getValue("relation")));
drt.setParentSelector((DataSelector)ds.getElement(attrs.getValue("parentSelector")));
drt.setParentTable((DataTable)ds.getElement(attrs.getValue("parentTable")));
} else if (qName.equals("dataRelation")) {
String relationName = attrs.getValue("name");
String parentColumnName = attrs.getValue("parentColumn");
String childColumnName = attrs.getValue("childColumn");
String parentTableName = parentColumnName.substring(0, parentColumnName.indexOf("."));
String childTableName = childColumnName.substring(0, childColumnName.indexOf("."));
try {
if ( tableNames.size() > 0 &&
tableNames.contains(parentTableName) &&
tableNames.contains(childTableName)) {
DataColumn parentColumn = (DataColumn)ds.getElement(parentColumnName);
DataColumn childColumn = (DataColumn)ds.getElement(childColumnName);
if ( parentColumn != null && childColumn != null ) {
if ( ds.getRelation(relationName) != null ) {
ds.dropRelation(relationName);
}
DataRelation relation = ds.createRelation(relationName);
relation.setParentColumn(parentColumn);
relation.setChildColumn(childColumn);
relationsAdded.add(relationName);
}
} else {
System.err.println("DataRelation: Either parent " + parentColumnName + " or child " + childColumnName +
" is missing in DataSource. Tables might not be loaded, or the respective columns might not be. " +
"Skipping.");
}
} catch ( Exception e ) {
System.out.println("failed on Parent: " + parentColumnName);
}
} else if (qName.equals("dataValue")) {
DataValue value = ds.createValue(attrs.getValue("name"));
value.setExpression(attrs.getValue("expression"));
}
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if (qName.equals("xs:element")) {
switch(elementDepth) {
case 1:
break;
case 2:
break;
case 3:
break;
default:
System.out.println("Error in DataSetParser");
}
elementDepth--;
}
}
public void endDocument() throws SAXException {
}
public List getTablesAdded() {
return tablesAdded;
}
public List getRelationsAdded() {
return relationsAdded;
}
}
}