package com.openMap1.mapper.actions;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.util.Vector;
import org.eclipse.jface.action.IAction;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.PlatformUI;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.xsd.XSDSchema; // a kind of EObject
import com.openMap1.mapper.presentation.MapperEditor;
import com.openMap1.mapper.presentation.DatabaseConnectWizard;
import com.openMap1.mapper.structures.SQLParser;
import com.openMap1.mapper.structures.XSDStructure;
import com.openMap1.mapper.structures.DBStructure;
import com.openMap1.mapper.converters.CSV_Wrapper;
import com.openMap1.mapper.core.MapperException;
import com.openMap1.mapper.util.FileUtil;
import com.openMap1.mapper.views.WorkBenchUtil;
import com.openMap1.mapper.ElementDef;
import com.openMap1.mapper.MappedStructure;
import com.openMap1.mapper.MapperPackage;
import com.openMap1.mapper.StructureType;
/**
* Action to read in an XML schema or RDBMS schema or csv file and use it as the basis for a mapped structure.
* After doing this action, the user needs to choose a complex type or element to be the
* root of the mapped structure, setting the attribute of the top Mapped Structure node
* @author robert
*
*/
public class AttachDataStructureActionDelegate extends MapperActionDelegate
implements IObjectActionDelegate {
static String CSV_WRAPPER_CLASSNAME = "com.openMap1.mapper.converters.CSV_Wrapper";
@Override
/**
* On running this action, do the following:
*
* (1) Find out what kind of structure definition the MappedStructure uses - XSD or RDBMS or csv
* (2) Show a file dialogue for the user to select an XSD or csv file, or a connection dialogue
* to make a database connection
* (3) Try to open the XSD file and read it into an ecore model,
* or open the csv
* or to open the database to get its metadata
* (4) If the editor is not open, open it
* (5) Set the 'data structure location' attribute on the top 'Mapped structure' node
* (6) Find the set of allowed values for the top element type
* (7) attach the XSDStructure to the root MappedStructure object
*/
public void run(IAction action) {
// (1) find out if the selected mapper file is expecting an XSD structure, or an RDMBS, or a csv file
boolean isDatabaseStructure =
(mappedStructure().getStructureType().equals(StructureType.RDBMS));
String wrapperClassName = mappedStructure().getMappingParameters().getWrapperClass();
boolean isCSVStructure = ((wrapperClassName != null) && (wrapperClassName.equals(CSV_WRAPPER_CLASSNAME)));
try{
if (isDatabaseStructure) runForDatabaseStructure();
else if (isCSVStructure) runForCSVStructure();
// the last else case covers structure types: XSD, V2
else runForXSDStructure();
}
catch (MapperException ex)
{
ex.printStackTrace();
showMessage(ex.getMessage());
}
}
private void runForDatabaseStructure() throws MapperException
{
// allow the user to open an sql schema file
String path = "";
String[] exts = {"*.sql"};
path = FileUtil.getFilePathFromUser(targetPart,exts,"Select SQL schema file",false);
// the user opened an SQL file
if (!(path.equals(""))) try
{
FileInputStream sqlStream = new FileInputStream(path);
Vector<String> lines = FileUtil.getLines(sqlStream);
SQLParser parser = new SQLParser(lines);
parser.parse();
// If the editor is not open, open it
MapperEditor me = OpenMapperEditor(selection);
if (me == null) return;
// expand the structure
ElementDef newRoot = parser.makeTableStructure();
setTreeStructure(me,newRoot);
}
catch (FileNotFoundException ex) {throw new MapperException(ex.getMessage());}
/* the user cancelled the opportunity to open an SQL file, so
* give the opportunity to open a database connection */
else if (path.equals(""))
{
// (2) show a dialog for the user to choose a database connection
DatabaseConnectWizard wizard = new DatabaseConnectWizard();
wizard.init(PlatformUI.getWorkbench(),(IStructuredSelection)selection);
WizardDialog dialog = new WizardDialog
(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),wizard);
dialog.open();
path = wizard.dbConnect().connectString();
// (3) get schema information from the database
Connection con = wizard.dbConnect().con();
DBStructure dbStructure = new DBStructure(con);
// (4) If the editor is not open, open it
MapperEditor me = OpenMapperEditor(selection);
if (me == null) return;
// (5) Set the 'data structure URL' property on the top 'Mapped structure' node
setStructureURLProperty(me, path);
// (6) find the set of allowed values for the top element type and name
me.propertyValueSetProvider().notifyNewValueSupplier
("MappedStructure","Top Element Type", dbStructure);
me.propertyValueSetProvider().notifyNewValueSupplier
("MappedStructure","Top Element Name", dbStructure);
// (7) attach the database Structure to the root MappedStructure object
WorkBenchUtil.mappingRoot(me).setStructureDefinition(dbStructure);
}
}
/**
* get a file name for an XML schema and read it
* (overridden for the V2 case)
* @throws MapperException
*/
public void runForXSDStructure() throws MapperException
{
String path = "";
// (2) show a dialog for the user to choose an XSD file
String[] exts = {"*.xsd"};
path = FileUtil.getFilePathFromUser(targetPart,exts,"Select Data Structure Definition",false);
if (path.equals("")) return;
// (3) Try to open the file and read it into an ECore model
URI uri = FileUtil.URIFromPath(path);
XSDSchema theSchema = XSDStructure.getXSDRoot(uri);
if (theSchema == null) {showMessage("Failed to open XML Schema");return;}
// (4) If the editor is not open, open it
MapperEditor me = OpenMapperEditor(selection);
if (me == null) return;
// (5) Set the 'data structure URL' property on the top 'Mapped structure' node
setStructureURLProperty(me, uri.toString());
// (6) find the set of allowed values for the top element type and name
XSDStructure xsd = new XSDStructure(theSchema);
me.propertyValueSetProvider().notifyNewValueSupplier
("MappedStructure","Top Element Type", xsd);
me.propertyValueSetProvider().notifyNewValueSupplier
("MappedStructure","Top Element Name", xsd);
// (7) attach the XSDStructure to the root MappedStructure object
mappedStructure().setStructureDefinition(xsd);
System.out.println("Final namespaces: " + mappedStructure().getMappingParameters().getNameSpaces().size());
}
/**
* extract a csv mapping tree structure from an example csv file
* @throws MapperException
*/
private void runForCSVStructure() throws MapperException
{
String path = "";
// (2) show a dialog for the user to choose a CSV file
String[] exts = {"*.csv"};
path = FileUtil.getFilePathFromUser(targetPart,exts,"Select Example of CSV Data Structure",false);
if (path.equals("")) return;
// (3) Try to open the csv file
Object input = null;
try
{
input = new FileInputStream(new File(path));
}
catch (Exception ex)
{throw new MapperException("Cannot open csv file at '" + path + "'");}
// (4) If the editor is not open, open it
MapperEditor me = OpenMapperEditor(selection);
if (me == null) return;
// (5) Set the 'data structure URL' property on the top 'Mapped structure' node
setStructureURLProperty(me, path);
// (6) find the set of allowed values for the top element type and name
CSV_Wrapper csvStructure = new CSV_Wrapper(WorkBenchUtil.mappingRoot(me),null);
csvStructure.getStructure(input);
me.propertyValueSetProvider().notifyNewValueSupplier
("MappedStructure","Top Element Type", csvStructure);
me.propertyValueSetProvider().notifyNewValueSupplier
("MappedStructure","Top Element Name", csvStructure);
// (7) attach the XSDStructure to the root MappedStructure object
mappedStructure().setStructureDefinition(csvStructure);
}
/**
* update the property 'XSDURL' of the top 'MappedStructure' node (but do not save the file)
*/
public boolean setStructureURLProperty(MapperEditor me, String path)
{
MappedStructure ms = WorkBenchUtil.mappingRoot(me);
if (ms == null) return false;
EditingDomain ed = me.editingDomain();
SetCommand sc2 = new SetCommand(ed,ms,
MapperPackage.eINSTANCE.getMappedStructure_StructureURL(),
path);
ed.getCommandStack().execute(sc2);
return true;
}
/**
* update the ElementDef tree structure attached to the top 'MappedStructure' node (but do not save the file)
*/
public boolean setTreeStructure(MapperEditor me, ElementDef newRoot)
{
MappedStructure ms = WorkBenchUtil.mappingRoot(me);
if (ms == null) return false;
EditingDomain ed = me.editingDomain();
SetCommand sc2 = new SetCommand(ed,ms,
MapperPackage.eINSTANCE.getMappedStructure_RootElement(),
newRoot);
ed.getCommandStack().execute(sc2);
return true;
}
}