package com.openMap1.mapper.actions;
import java.util.Enumeration;
import org.eclipse.jface.action.IAction;
import org.eclipse.swt.widgets.Shell;
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.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import com.openMap1.mapper.core.MapperException;
import com.openMap1.mapper.views.DataSourceView;
import com.openMap1.mapper.views.LicenceDialog;
import com.openMap1.mapper.views.WorkBenchUtil;
import com.openMap1.mapper.presentation.TranslateDestinationWizard;
import com.openMap1.mapper.util.EclipseFileUtil;
import com.openMap1.mapper.util.GenUtil;
import com.openMap1.mapper.util.SOAPClient;
import com.openMap1.mapper.query.DataSource;
import com.openMap1.mapper.reader.MDLXOReader;
import com.openMap1.mapper.reader.XOReader;
import com.openMap1.mapper.writer.MappedXMLWriter;
import com.openMap1.mapper.writer.XMLObjectGetter;
import com.openMap1.mapper.writer.objectGetter;
import com.openMap1.mapper.writer.ProcedureCompiler;
import com.openMap1.mapper.writer.ProcedureWriterStub;
import com.openMap1.mapper.MappedStructure;
import java.util.Vector;
/**
* superclass for action classes TranslateActionDelegate to do a translation
* from every active data source to the selected mapping set,
* and MakeXSLTActionDelegate to generate XSLT.
*
* In both cases the sequence is :
*
* (1) Find the active sources in the sources view, and check that they have the same class
* model as the mapping set for the structure being translated to;
* if not show an error dialogue
*
* (2) For each active source, show a Wizard file selection page to choose a destination file
* (for the translated XML, or the XSLT)
*
* (3) Check if the mapping set has an up-to-date writing procedure file; if not, create it
* using interface ProcedureCompiler
*
* (4) For each active source, either do the translation using class Translator, or
* generate the XSLT using class XSLGenerator
*
* @author robert
*
*/
public abstract class MakeTranslationActionDelegate extends MapperActionDelegate
implements IObjectActionDelegate {
protected boolean runTracing = false;
protected boolean tracing = false;
abstract public boolean isXSLTGeneration();
public void run(IAction action) {
try{
// (0) for XSLT Generation, check that the user has a licence
if (isXSLTGeneration())
{
String email = SOAPClient.getStoredEmail();
if (email == null)
throw new MapperException("You cannot generate XSLT without first running some Java translations.");
boolean newKeySupplied = false;
String xslKey = SOAPClient.getXSLTKey(); // existing key, if there is one; "" otherwise
// only one chance to set the licence key and accept the licence terms
if (!LicenceDialog.isValidXSLKey(xslKey))
{
newKeySupplied = true;
Shell shell = targetPart.getSite().getShell();
LicenceDialog licenceDialog = new LicenceDialog(shell, "Mapper XSLT Generator License", LicenceDialog.XSLT_licence_text());
xslKey = (String)licenceDialog.open();
}
if (xslKey.equals(LicenceDialog.DECLINED))
throw new MapperException("Licence terms declined");
if (!LicenceDialog.isValidXSLKey(xslKey))
throw new MapperException("Invalid licence key");
// if a valid new licence key has been supplied, save it
if (newKeySupplied) SOAPClient.setXSLTKey(xslKey);
}
/* (1) check that there are some active data sources,
* and that the class model of the mapping set is that of the active sources */
DataSourceView dataSourceView = WorkBenchUtil.getDataSourceView(true);
if (dataSourceView == null)
{showMessage("There is no data source view to define sources for the translation");return;}
Vector<DataSource> activeSources = dataSourceView.getActiveDataSources();
if (activeSources.size() == 0)
{showMessage("There are no active data sources for the translation");return;}
DataSource ds1 = activeSources.get(0);
String targetClassModel = mappedStructure().getUMLModelURL();
String sourceClassModel = ds1.getReader().ms().getUMLModelURL();
if (!sourceClassModel.equals(targetClassModel))
{showMessage("Data source mappings and target mappings do not have the same class model");return;}
/* (2) For each active source, show a Wizard file selection page to choose
* a destination file (for the translated XML, or the XSLT) */
String resultFileExtension = mappedStructure().getExtensions()[0].substring(2);
TranslateDestinationWizard destWizard =
new TranslateDestinationWizard(activeSources,isXSLTGeneration(),resultFileExtension);
destWizard.init(PlatformUI.getWorkbench(),(IStructuredSelection)selection);
WizardDialog dialog = new WizardDialog(WorkBenchUtil.getShell(),destWizard);
dialog.open();
/* (3) make up-to-date writing procedure files for the mapping set and all
* those it imports; (done remotely using ProcedureCompilerStub) */
makeAllProcedureFiles(mappedStructure());
/* (4) For each active source, either do the translation using class Translator, or
* generate the XSLT using class XSLGenerator */
for (int i = 0; i < destWizard.destinationFiles().size(); i++)
{
IFile destFile = destWizard.destinationFiles().get(i);
DataSource ds = activeSources.get(i);
XOReader reader = ds.getReader();
objectGetter oGet = null;
if (reader instanceof MDLXOReader)
oGet = new XMLObjectGetter((MDLXOReader)reader);
else if (reader instanceof objectGetter)
oGet = (objectGetter)reader;
else throw new MapperException("Cannot make objectGetter");
if (!isXSLTGeneration())
{
MappedXMLWriter translator = new MappedXMLWriter(EclipseFileUtil.proceduresFile(mappedStructure()),oGet,
mappedStructure(), null, destFile, runTracing);
translator.writeXML();
}
else if (isXSLTGeneration())
{
doXSLTGeneration(reader,destFile,oGet);
}
}
}
catch (Exception ex)
{
GenUtil.surprise(ex,"Translating");
showMessage("Failed to run writing procedures: " + ex.getMessage());
}
}
/**
* this method is defined to remove the compiler dependence of
* MakeTranslationSActionDelegate on the class that implements interface XSLGenerator
* @param reader
* @param destFile
* @param oGet
*/
abstract public void doXSLTGeneration(XOReader reader,IFile destFile,objectGetter oGet) throws MapperException;
/**
* Make and store the wproc files for a mapping set and all those
* which it imports, directly or indirectly
* @param mappedStructure
* @throws MapperException
* @throws CoreException
*/
public static void makeAllProcedureFiles(MappedStructure mappedStructure)
throws MapperException, CoreException
{
for (Enumeration<MappedStructure> en = mappedStructure.getAllImportedMappingSets().elements();en.hasMoreElements();)
makeProcedureFile(en.nextElement());
}
/**
* make and store a wproc file
* @param mappedStructure the mapping set it corresponds to
* @return the ProcedureCompiler that wrote the IFile (and knows the CompilationIssues)
* @throws MapperException
* @throws CoreException
*/
public static ProcedureCompiler makeProcedureFile(MappedStructure mappedStructure)
throws MapperException, CoreException
{
// make a handle for the procedures file in the correct sub-folder of the Translators folder
IFile proceduresFile = EclipseFileUtil.proceduresFile(mappedStructure);
// (the handle should never be null)
if (proceduresFile == null) throw new MapperException("Null Procedures file");
// (message channel is null - the work is done on the server)
ProcedureCompiler procWriter = new ProcedureWriterStub(mappedStructure,null);
// create the write procedures and save them
boolean codeTrace = false; // trace is on the server
procWriter.generateProcedures(proceduresFile,codeTrace);
return procWriter;
}
protected void trace(String s) {if (tracing) System.out.println(s);}
}