/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.relational.ui.wizards;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.relational.RelationalConstants;
import org.teiid.designer.relational.RelationalPlugin;
import org.teiid.designer.relational.model.RelationalAccessPattern;
import org.teiid.designer.relational.model.RelationalColumn;
import org.teiid.designer.relational.model.RelationalForeignKey;
import org.teiid.designer.relational.model.RelationalIndex;
import org.teiid.designer.relational.model.RelationalModel;
import org.teiid.designer.relational.model.RelationalModelFactory;
import org.teiid.designer.relational.model.RelationalParameter;
import org.teiid.designer.relational.model.RelationalPrimaryKey;
import org.teiid.designer.relational.model.RelationalProcedure;
import org.teiid.designer.relational.model.RelationalProcedureResultSet;
import org.teiid.designer.relational.model.RelationalReference;
import org.teiid.designer.relational.model.RelationalTable;
import org.teiid.designer.relational.model.RelationalUniqueConstraint;
import org.teiid.designer.relational.model.RelationalView;
import org.teiid.designer.relational.ui.UiConstants;
import org.teiid.designer.relational.ui.textimport.RelationalRowFactory;
import org.teiid.designer.tools.textimport.ui.wizards.AbstractObjectProcessor;
import org.teiid.designer.tools.textimport.ui.wizards.IRowObject;
import org.teiid.designer.ui.common.viewsupport.StatusInfo;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Creates relational model contents based on an input <code>RelationalModel</code> and a target <code>ModelResource</code>
*
*
*
* @since 8.0
*/
public class RelationalModelXmlTextFileProcessor extends AbstractObjectProcessor implements RelationalConstants {
//============================================================================================================================
// Static Constants
static final String TAG_RELATIONAL_MODEL = "relational-model"; //$NON-NLS-1$
static final String TAG_TABLE = "table"; //$NON-NLS-1$
static final String TAG_COLUMN = "column"; //$NON-NLS-1$
static final String TAG_VIEW = "view"; //$NON-NLS-1$
static final String TAG_PRIMARY_KEY = "primary-key"; //$NON-NLS-1$
static final String TAG_UNIQUE_CONSTRAINT = "unique-constraint"; //$NON-NLS-1$
static final String TAG_FOREIGN_KEY = "foreign-key"; //$NON-NLS-1$
static final String TAG_ACCESS_PATTERN = "access-pattern"; //$NON-NLS-1$
static final String TAG_PROCEDURE = "procedure"; //$NON-NLS-1$
static final String TAG_PARAMETER = "parameter"; //$NON-NLS-1$
static final String TAG_RESULT_SET = "result-set"; //$NON-NLS-1$
static final String TAG_INDEX = "index"; //$NON-NLS-1$
static final String TAG_COLUMN_REFERENCE = "column-reference"; //$NON-NLS-1$
static final String TAG_COLUMN_TABLE_REFERENCE = "column-table-reference"; //$NON-NLS-1$
private static final String KEY_NAME = "name"; //$NON-NLS-1$
private static final String KEY_TABLE_NAME = "tableName"; //$NON-NLS-1$
public StatusInfo statusInfo;
//============================================================================================================================
// Static Methods
@SuppressWarnings( "unused" )
private IProgressMonitor monitor;
private RelationalModel relationalModel;
/**
*
* @since 4.2
*/
public RelationalModelXmlTextFileProcessor() {
super();
statusInfo = new StatusInfo(RelationalPlugin.PLUGIN_ID);
}
/**
*
* @param targetResource
*/
public void buildModel(ModelResource targetResource, IProgressMonitor progressMonitor) {
RelationalModelFactory factory = new RelationalModelFactory();
factory.build(targetResource, this.relationalModel, progressMonitor);
}
public RelationalModel getRelationalModel() {
return this.relationalModel;
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.tools.textimport.ui.wizards.AbstractObjectProcessor#loadLinesFromFile(java.lang.String)
*/
@Override
public Collection loadLinesFromFile( String fileStr ) {
Collection lines = super.loadLinesFromFile(fileStr);
relationalModel = parseFile(fileStr);
return lines;
}
private RelationalModel parseFile(String xmlFileUrl) {
IPath filePath = new Path(xmlFileUrl);
String fileName = filePath.lastSegment();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
statusInfo = new StatusInfo(RelationalPlugin.PLUGIN_ID);
RelationalModel relModel = new RelationalModel("bogus"); //$NON-NLS-1$
try {
//Using factory get an instance of document builder
DocumentBuilder db = factory.newDocumentBuilder();
//parse using builder to get DOM representation of the XML file
Document document = db.parse(xmlFileUrl);
//DOMConfiguration config = document.getDomConfig();
//config.setParameter("error-handler",new MyErrorHandler());
// config.setParameter("schema-type", "http://www.w3.org/2001/XMLSchema");
// config.setParameter("validate", Boolean.TRUE);
// document.normalizeDocument();
//get the root element
Element root = document.getDocumentElement();
if( getTagWithoutPrefix(root.getTagName()).equalsIgnoreCase(TAG_RELATIONAL_MODEL)) {
//get a nodelist of elements
NodeList children = root.getChildNodes();
Collection<Node> indexNodes = new ArrayList<Node>();
if(children != null && children.getLength() > 0) {
for(int i = 0 ; i < children.getLength();i++) {
Node child = children.item(i);
String name = getTagWithoutPrefix(child.getNodeName());
int type = getType(name);
switch(type) {
case TYPES.TABLE: {
Properties props = getProperties(child.getAttributes());
RelationalTable table = new RelationalTable();
relModel.addChild(table);
table.setProperties(props);
Node primaryKeyElement = null;
Node uniqueConstraintElement = null;
Collection<Node> accessPatternNodes = new ArrayList<Node>();
Collection<Node> foreignKeyNodes = new ArrayList<Node>();
// Create Table Children. Do not process KEYS until done with children
// DO NOT PROCESS FK's until ALL tables are complete
NodeList tableChildren = child.getChildNodes();
if(tableChildren != null && tableChildren.getLength() > 0) {
for(int j = 0 ; j < tableChildren.getLength();j++) {
//get the employee element
Node tableChild = tableChildren.item(j);
String tableChildName = getTagWithoutPrefix(tableChild.getNodeName());
int tableChildType = getType(tableChildName);
switch(tableChildType) {
case TYPES.COLUMN: {
Properties columnProps = getProperties(tableChild.getAttributes());
RelationalColumn column = new RelationalColumn();
table.addColumn(column);
column.setProperties(columnProps);
} break;
case TYPES.PK: {
primaryKeyElement = tableChild;
} break;
case TYPES.UC: {
uniqueConstraintElement = tableChild;
} break;
case TYPES.AP: {
accessPatternNodes.add(tableChild);
} break;
case TYPES.FK: {
foreignKeyNodes.add(tableChild);
} break;
}
}
}
processPrimaryKey(primaryKeyElement, table);
processUniqueConstraint(uniqueConstraintElement, table);
for( Node apNode : accessPatternNodes) {
processAccessPattern( apNode, table);
}
for( Node fkNode : foreignKeyNodes) {
processForeignKey(fkNode, table);
}
} break;
case TYPES.VIEW: {
Properties props = getProperties(child.getAttributes());
RelationalView view = new RelationalView();
relModel.addChild(view);
view.setProperties(props);
Collection<Node> accessPatternNodes = new ArrayList<Node>();
// Create Table Children. Do not process KEYS until done with children
// DO NOT PROCESS FK's until ALL tables are complete
NodeList tableChildren = child.getChildNodes();
if(tableChildren != null && tableChildren.getLength() > 0) {
for(int j = 0 ; j < tableChildren.getLength();j++) {
//get the employee element
Node tableChild = tableChildren.item(j);
String tableChildName = getTagWithoutPrefix(tableChild.getNodeName());
int tableChildType = getType(tableChildName);
switch(tableChildType) {
case TYPES.COLUMN: {
Properties columnProps = getProperties(tableChild.getAttributes());
RelationalColumn column = new RelationalColumn();
view.addColumn(column);
column.setProperties(columnProps);
} break;
case TYPES.AP: {
accessPatternNodes.add(tableChild);
} break;
}
}
}
for( Node apNode : accessPatternNodes) {
processAccessPattern( apNode, view);
}
} break;
case TYPES.PROCEDURE: {
Properties props = getProperties(child.getAttributes());
RelationalProcedure proc = new RelationalProcedure();
relModel.addChild(proc);
proc.setProperties(props);
NodeList procChildren = child.getChildNodes();
if(procChildren != null && procChildren.getLength() > 0) {
for(int j = 0 ; j < procChildren.getLength();j++) {
//get the employee element
Node procChild = procChildren.item(j);
String tableChildName = getTagWithoutPrefix(procChild.getNodeName());
int tableChildType = getType(tableChildName);
switch(tableChildType) {
case TYPES.PARAMETER: {
Properties paramProps = getProperties(procChild.getAttributes());
RelationalParameter param = new RelationalParameter();
proc.addParameter(param);
param.setProperties(paramProps);
} break;
case TYPES.RESULT_SET: {
Properties rsProps = getProperties(procChild.getAttributes());
RelationalProcedureResultSet resultSet = new RelationalProcedureResultSet();
resultSet.setProperties(rsProps);
proc.setResultSet(resultSet);
NodeList rsChildren = procChild.getChildNodes();
if(rsChildren != null && rsChildren.getLength() > 0) {
for(int k = 0 ; k < rsChildren.getLength();k++) {
//get the employee element
Node rsChild = rsChildren.item(k);
String rsChildName = getTagWithoutPrefix(rsChild.getNodeName());
int rsChildType = getType(rsChildName);
switch(rsChildType) {
case TYPES.COLUMN: {
Properties columnProps = getProperties(rsChild.getAttributes());
RelationalColumn column = new RelationalColumn();
column.setProperties(columnProps);
resultSet.addColumn(column);
} break;
}
}
}
} break;
}
}
}
} break;
case TYPES.INDEX: {
indexNodes.add(child);
} break;
default: {
if( !name.equalsIgnoreCase("#text")) { //$NON-NLS-1$
String message = UiConstants.Util.getString("RelationalModelXmlTextFileProcessor.importRelationalModelHasBugsElement", name); //$NON-NLS-1$
statusInfo.setWarning(message);
}
}
}
//get the Employee object
}
}
for( Node indexNode : indexNodes ) {
Properties props = getProperties(indexNode.getAttributes());
RelationalIndex index = new RelationalIndex();
relModel.addChild(index);
index.setProperties(props);
NodeList indexChildren = indexNode.getChildNodes();
if(indexChildren != null && indexChildren.getLength() > 0) {
for(int j = 0 ; j < indexChildren.getLength();j++) {
Node indexChild = indexChildren.item(j);
String indexChildName = getTagWithoutPrefix(indexChild.getNodeName());
if( indexChildName.equalsIgnoreCase(TAG_COLUMN_TABLE_REFERENCE) ) {
String tableName = indexChild.getAttributes().getNamedItem(KEY_TABLE_NAME).getNodeValue();
String colName = indexChild.getAttributes().getNamedItem(KEY_NAME).getNodeValue();
for( RelationalReference child : relModel.getChildren() ) {
if( child.getType() == TYPES.TABLE && child.getName().equalsIgnoreCase( tableName ) ) {
for( RelationalColumn column : ((RelationalTable)child).getColumns()) {
if( column.getName().equalsIgnoreCase(colName) ) {
index.addColumn(column);
}
}
}
}
}
}
}
}
}
}catch(ParserConfigurationException pce) {
String title = UiConstants.Util.getString("RelationalModelXmlTextFileProcessor.importRelationalModelXmlParsingError.title"); //$NON-NLS-1$
String message = UiConstants.Util.getString("RelationalModelXmlTextFileProcessor.importRelationalModelXmlParsingError", fileName) + pce.getMessage(); //$NON-NLS-1$
MessageDialog.openError(Display.getCurrent().getActiveShell(), title, message);
statusInfo.setError(message);
relModel = null;
}catch(SAXException se) {
String title = UiConstants.Util.getString("RelationalModelXmlTextFileProcessor.importRelationalModelXmlParsingError.title"); //$NON-NLS-1$
String message = UiConstants.Util.getString("RelationalModelXmlTextFileProcessor.importRelationalModelXmlParsingError", fileName) + se.getMessage(); //$NON-NLS-1$
MessageDialog.openError(Display.getCurrent().getActiveShell(), title, message);
statusInfo.setError(message);
relModel = null;
}catch(IOException ioe) {
String title = UiConstants.Util.getString("RelationalModelXmlTextFileProcessor.importRelationalModelXmlParsingError.title"); //$NON-NLS-1$
String message = UiConstants.Util.getString("RelationalModelXmlTextFileProcessor.importRelationalModelXmlParsingError", fileName) + ioe.getMessage(); //$NON-NLS-1$
MessageDialog.openError(Display.getCurrent().getActiveShell(), title, message);
statusInfo.setError(message);
relModel = null;
}
return relModel;
}
private void processPrimaryKey(Node primaryKeyNode, RelationalTable table) {
if( primaryKeyNode == null ) {
return;
}
Properties pkProps = getProperties(primaryKeyNode.getAttributes());
RelationalPrimaryKey pk = new RelationalPrimaryKey();
pk.setProperties(pkProps);
table.setPrimaryKey(pk);
NodeList pkChildren = primaryKeyNode.getChildNodes();
if(pkChildren != null && pkChildren.getLength() > 0) {
for(int j = 0 ; j < pkChildren.getLength();j++) {
Node pkChild = pkChildren.item(j);
String pkChildName = getTagWithoutPrefix(pkChild.getNodeName());
if( pkChildName.equalsIgnoreCase(TAG_COLUMN_REFERENCE) ) {
String colName = pkChild.getAttributes().getNamedItem(KEY_NAME).getNodeValue();
for( RelationalColumn column : table.getColumns()) {
if( column.getName().equalsIgnoreCase(colName) ) {
pk.addColumn(column);
}
}
}
}
}
}
private void processForeignKey(Node foreignKeyNode, RelationalTable table) {
if( foreignKeyNode == null ) {
return;
}
Properties fkProps = getProperties(foreignKeyNode.getAttributes());
RelationalForeignKey fk = new RelationalForeignKey();
fk.setProperties(fkProps);
table.addForeignKey(fk);
NodeList fkChildren = foreignKeyNode.getChildNodes();
if(fkChildren != null && fkChildren.getLength() > 0) {
for(int j = 0 ; j < fkChildren.getLength();j++) {
Node fkChild = fkChildren.item(j);
String pkChildName = getTagWithoutPrefix(fkChild.getNodeName());
if( pkChildName.equalsIgnoreCase(TAG_COLUMN_REFERENCE) ) {
String colName = fkChild.getAttributes().getNamedItem(KEY_NAME).getNodeValue();
for( RelationalColumn column : table.getColumns()) {
if( column.getName().equalsIgnoreCase(colName) ) {
fk.addColumn(column);
}
}
}
}
}
}
private void processAccessPattern(Node accessPatternNode, RelationalTable table) {
if( accessPatternNode == null ) {
return;
}
Properties acProps = getProperties(accessPatternNode.getAttributes());
RelationalAccessPattern ac = new RelationalAccessPattern();
ac.setProperties(acProps);
table.addAccessPattern(ac);
NodeList acChildren = accessPatternNode.getChildNodes();
if(acChildren != null && acChildren.getLength() > 0) {
for(int j = 0 ; j < acChildren.getLength();j++) {
Node acChild = acChildren.item(j);
String acChildName = getTagWithoutPrefix(acChild.getNodeName());
if( acChildName.equalsIgnoreCase(TAG_COLUMN_REFERENCE) ) {
String colName = acChild.getAttributes().getNamedItem(KEY_NAME).getNodeValue();
for( RelationalColumn column : table.getColumns()) {
if( column.getName().equalsIgnoreCase(colName) ) {
ac.addColumn(column);
}
}
}
}
}
}
private void processUniqueConstraint(Node uniqueConstraintNode, RelationalTable table) {
if( uniqueConstraintNode == null ) {
return;
}
Properties ucProps = getProperties(uniqueConstraintNode.getAttributes());
RelationalUniqueConstraint uc = new RelationalUniqueConstraint();
uc.setProperties(ucProps);
table.setUniqueConstraint(uc);
NodeList ucChildren = uniqueConstraintNode.getChildNodes();
if(ucChildren != null && ucChildren.getLength() > 0) {
for(int j = 0 ; j < ucChildren.getLength();j++) {
Node ucChild = ucChildren.item(j);
String ucChildName = getTagWithoutPrefix(ucChild.getNodeName());
if( ucChildName.equalsIgnoreCase(TAG_COLUMN_REFERENCE) ) {
String colName = ucChild.getAttributes().getNamedItem(KEY_NAME).getNodeValue();
for( RelationalColumn column : table.getColumns()) {
if( column.getName().equalsIgnoreCase(colName) ) {
uc.addColumn(column);
}
}
}
}
}
}
private Properties getProperties(NamedNodeMap attributeMap) {
Properties props = new Properties();
if( attributeMap != null && attributeMap.getLength() > 0 ) {
for( int i=0; i< attributeMap.getLength(); i++ ) {
Node item = attributeMap.item(i);
props.put(item.getNodeName(), item.getNodeValue());
}
}
return props;
}
public Collection createRowObjsFromStrings(Collection rowStrings) {
Iterator iter = rowStrings.iterator();
String nextStr = null;
RelationalRowFactory factory = new RelationalRowFactory();
Collection stringRows = new ArrayList();
IRowObject nextRow = null;
while( iter.hasNext() ) {
nextStr = (String)iter.next();
nextRow = factory.createRowObject(nextStr);
if( nextRow != null && nextRow.isValid() )
stringRows.add(nextRow);
else {
logParsingError(nextStr);
}
}
return stringRows;
}
private int getType(String objType) {
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.ACCESSPATTERN) ) {
return TYPES.AP;
}
if (objType.trim().equalsIgnoreCase(TYPES_LITERAL.CATALOG)) {
return TYPES.CATALOG;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.COLUMN) ) {
return TYPES.COLUMN;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.FOREIGNKEY) ) {
return TYPES.FK;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.INDEX) ) {
return TYPES.INDEX;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.MODEL) ) {
return TYPES.MODEL;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.PARAMETER) ) {
return TYPES.PARAMETER;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.PRIMARYKEY) ) {
return TYPES.PK;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.PROCEDURE) ) {
return TYPES.PROCEDURE;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.RESULTSET) ) {
return TYPES.RESULT_SET;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.SCHEMA) ) {
return TYPES.SCHEMA;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.TABLE) ) {
return TYPES.TABLE;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.UNIQUECONSTRAINT) ) {
return TYPES.UC;
}
if( objType.trim().equalsIgnoreCase(TYPES_LITERAL.VIEW) ) {
return TYPES.VIEW;
}
return TYPES.UNDEFINED;
}
private String getTagWithoutPrefix(String tagStr) {
int indexOfColon = tagStr.indexOf(':');
if( indexOfColon < 0 ) {
return tagStr;
}
return tagStr.substring(indexOfColon+1);
}
public void setProgressMonitor(IProgressMonitor monitor) {
this.monitor = monitor;
}
public StatusInfo getStatusInfo() {
return this.statusInfo;
}
}