package com.openMap1.mapper.views; import java.util.Iterator; import java.util.Vector; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.graphics.Image; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IViewSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.IMemento; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.ViewPart; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EPackage; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.viewers.CheckboxTableViewer; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.wizard.WizardDialog; import org.w3c.dom.Document; import org.w3c.dom.Element; import com.openMap1.mapper.presentation.DatabaseConnectWizard; import com.openMap1.mapper.query.DataSource; import com.openMap1.mapper.reader.XOReader; import com.openMap1.mapper.core.MapperException; import com.openMap1.mapper.core.StructureMismatch; import com.openMap1.mapper.core.TranslationIssue; import com.openMap1.mapper.actions.TranslationTestAction; import com.openMap1.mapper.actions.WriteCrossMappingsAction; import com.openMap1.mapper.util.FileUtil; import com.openMap1.mapper.util.ModelUtil; import com.openMap1.mapper.util.SystemMessageChannel; import com.openMap1.mapper.util.messageChannel; import com.openMap1.mapper.util.XMLUtil; import com.openMap1.mapper.util.GenUtil; import com.openMap1.mapper.MappedStructure; import com.openMap1.mapper.StructureType; /** * shows a set of data sources. Each data source is a row of the view, and consists of * a mapping set, an instance mapped, and the class model it is mapped to. * All data sources must have the same class model. Any * data source may be active or not. * * @author robert * */ public class DataSourceView extends ViewPart implements SaveableView{ private CheckboxTableViewer viewer; private Table tab; private Action addDataSourceAction; private Action saveDataSourceSetAction; private Action restoreDataSourceSetAction; private Action removeAllDataSourcesAction; private Action removeSelectedDataSourcesAction; private Action translationTestAction; private Action crossMappingsAction; private Action defineFHIRSearchAction; // this is the model, which should be kept synchronised with the viewer private Vector<DataSource> dataSources = new Vector<DataSource>(); public Vector<DataSource> dataSources() {return dataSources;} private String instanceLocation; private Vector<String> columnHeaders; private LabelledEClass copiedLabelledEClass = null; /** set the node that has been copied, for later paste of simplification annotations */ public void setCopiedLabelledEClass(LabelledEClass copied) {copiedLabelledEClass= copied;} /** get the node that has been copied, for later paste of simplification annotations */ public LabelledEClass getCopiedLabelledEClass() {return copiedLabelledEClass;} private String annotationURI; /** set the annotation uri */ public void setAnnotationURI(String annotationURI) {this.annotationURI = annotationURI;} /** get the annotation uri */ public String getAnnotationURI() {return annotationURI;} //------------------------------------------------------------------------------------- // Refresh all data sources //------------------------------------------------------------------------------------- /** * Ensure that all active data sources are connected to an up-to-date mapping set and XML * instance (e.g before running a query, or before a translation test) * in case either the mapping set or the instance has been edited since the data source was made * * If any data source cannot be refreshed (eg because the mapping set has been * deleted or its name changed) write a warning and make that source inactive */ public void refreshAllActiveSources(boolean allowNewPasswords) { // refresh the 'active' status of all data sources, from the checkboxes in the view table getActiveDataSources(); // now address only data sources which are active for (Iterator<DataSource> it = dataSources().iterator();it.hasNext();) { DataSource ds = it.next(); if (ds.isActive()) { boolean connected = false; String reason = ""; try { MappedStructure mapStructure = ds.getFreshMappedStructure(); // relational data sources; if not connected, possibly ask the user for a user name and password if (mapStructure.getStructureType() == StructureType.RDBMS) { if ((!ds.isConnected()) && (allowNewPasswords)) getNewUserNameAndPassword(ds); // may throw an Exception connected = ds.isConnected(); } // non-relational sources; refresh, in case the XML instance has changed else if (mapStructure.getStructureType() != StructureType.RDBMS) { ds.refresh(); connected = true; } } // something unexpected; record the reason catch (MapperException ex) { reason = "(" + ex.getMessage() + ")"; connected = false; } // if you could not open the data source file or database for any reason, make it inactive if (!connected) { ds.setIsActive(false); // make the data source know it is inactive viewer.setChecked(ds, false); // make the view and the checkbox know it is inactive String warning = "Data source " + ds.getCode() + " could not be refreshed" + reason + ", and has been made inactive."; MessageDialog.openError(getSite().getShell(), "Data sources changed", warning); } } } } /** * get a new user name and password for a relational data source, and attempt to connect it * @param ds * @return * @throws MapperException e.g if the user name and password are not accepted */ private boolean getNewUserNameAndPassword(DataSource ds) throws MapperException { boolean dataSourceIsConnected = false; MappedStructure mapStructure = ds.getFreshMappedStructure(); // allow the user to input a new user name and password for the database DatabaseConnectWizard wizard = new DatabaseConnectWizard(); wizard.init(PlatformUI.getWorkbench(),null); // no selection has been right-clicked WizardDialog dialog = new WizardDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),wizard); // don't allow the user to input a new jdbc connect string; that is defined in the mapping set wizard.fixJDBCString(mapStructure.getStructureURL()); dialog.open(); if (wizard.finishedSuccessfully()) // user did not cancel { String userName = wizard.getUserName(); String password = wizard.getPassword(); // mapStructure.connectToRDB(userName, password); // seems redundant given next line ds.connect(userName, password); // may throw an Exception dataSourceIsConnected = ds.isConnected(); } return dataSourceIsConnected; } //------------------------------------------------------------------------------------- // Initialisation //------------------------------------------------------------------------------------- /** * This creates the viewer and initializes it. */ public void createPartControl(Composite parent) { // create the viewer and its table createViewer(parent); // make the actions that will be items on the menu of this view makeActions(); // attach the menu to this view contributeToActionBars(); } public void createViewer(Composite parent) { tab = new Table(parent, SWT.CHECK | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL); viewer = new CheckboxTableViewer(tab); viewer.setLabelProvider(new DataSourceTableLabelProvider()); tab.setHeaderVisible(true); tab.setLinesVisible(true); makeTableColumns(tab); /* add a listener for selection changes, which tells the data sources * which ones are selected. This is not currently used, because selecting * the drop-down menu immediately de-selects all the rows; so you * cannot make a drop-down menu item (or even its enablement) depend on the selected rows. * A brilliant catch-22. */ viewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { // de-select all data sources for (Iterator<DataSource> it = dataSources.iterator();it.hasNext();) it.next().setIsSelected(false); // select only those in the selection for (Iterator<?> is = ((IStructuredSelection)event.getSelection()).iterator();is.hasNext();) ((DataSource)is.next()).setIsSelected(true); } }); // populate the viewer with any existing Data sources, remembered by init(..)from the last session for (Iterator <DataSource> it = dataSources.iterator();it.hasNext();) { DataSource qs = it.next(); viewer.add(qs); viewer.setChecked(qs, qs.isActive()); } } private void makeTableColumns(Table tab) { columnHeaders = new Vector<String>(); String[] columnNames = new String[]{"Code","Type","Source","Mappings","Class Model"}; int[] columnWidths = new int[] {40,60,200,200,200}; int[] columnAlignments = new int[] {SWT.LEFT,SWT.LEFT,SWT.LEFT,SWT.LEFT,SWT.LEFT}; for (int i = 0; i < columnNames.length;i++) { TableColumn col = new TableColumn(tab,columnAlignments[i]); col.setText(columnNames[i]); col.setWidth(columnWidths[i]); columnHeaders.add(columnNames[i]); } } class DataSourceTableLabelProvider extends LabelProvider implements ITableLabelProvider { public String getColumnText(Object element, int index) { DataSource qs = (DataSource)element; switch (index) { case 0: return qs.getCode(); case 1: return qs.sourceType(); case 2: return stripPlatform(qs.instanceURIString()); case 3: return stripPlatform(qs.mappingSetURIString()); case 4: return stripPlatform(qs.classModelURIString()); default: return ("unknown " + index); } } // strip the repetitive prefix from platform URIs private String stripPlatform(String uri) { String prefix = "platform:/resource"; String stripped = uri; if (stripped.startsWith(prefix)) stripped = stripped.substring(prefix.length()); return stripped; } public Image getColumnImage(Object element, int index) {return null;} } //------------------------------------------------------------------------------------- // Menu //------------------------------------------------------------------------------------- private void makeActions() { addDataSourceAction = new Action() { public void run() { doAddDataSource(); } }; addDataSourceAction.setText("Add a Data Source"); addDataSourceAction.setToolTipText("Add a set of mappings and an XML Instance to be queried"); addDataSourceAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages(). getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK)); removeSelectedDataSourcesAction = new Action() { public void run() { doRemoveInactiveDataSources(); } }; removeSelectedDataSourcesAction.setText("Remove inactive data sources"); removeSelectedDataSourcesAction.setToolTipText("Remove inactive (unchecked) Data Sources"); removeSelectedDataSourcesAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages(). getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK)); // removeSelectedDataSourcesAction.setEnabled(false); removeAllDataSourcesAction = new Action() { public void run() { doClearAllDataSources(); } }; removeAllDataSourcesAction.setText("Remove all Data Sources"); removeAllDataSourcesAction.setToolTipText("Remove all Data Sources"); removeAllDataSourcesAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages(). getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK)); translationTestAction = new TranslationTestAction(getSite().getShell(),this); saveDataSourceSetAction = new Action() { public void run() { doSaveDataSourceSet(); } }; saveDataSourceSetAction.setText("Save Data Source Set to file"); saveDataSourceSetAction.setToolTipText("Create an XML file from which this Data source set can be re-created"); saveDataSourceSetAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages(). getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK)); restoreDataSourceSetAction = new Action() { public void run() { loadSavedDataSourceSet(); } }; restoreDataSourceSetAction.setText("Restore Data Source Set from file"); restoreDataSourceSetAction.setToolTipText("Re-create a Data source set from an XML file"); restoreDataSourceSetAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages(). getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK)); crossMappingsAction = new WriteCrossMappingsAction(this); defineFHIRSearchAction = new Action() { public void run() { doDefineFHIRSearch(); } }; defineFHIRSearchAction.setText("Define FHIR Search"); defineFHIRSearchAction.setToolTipText("Define a FHIR search for use on all active networked FHIR data sources"); defineFHIRSearchAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages(). getImageDescriptor(ISharedImages.IMG_OBJS_INFO_TSK)); } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); fillLocalPullDown(bars.getMenuManager()); } private void fillLocalPullDown(IMenuManager manager) { manager.add(addDataSourceAction); manager.add(removeSelectedDataSourcesAction); manager.add(removeAllDataSourcesAction); manager.add(saveDataSourceSetAction); manager.add(translationTestAction); manager.add(restoreDataSourceSetAction); manager.add(crossMappingsAction); manager.add(defineFHIRSearchAction); } //------------------------------------------------------------------------------------------ // saving the state of the view //------------------------------------------------------------------------------------------ /** @return the label provider for the view */ public ITableLabelProvider labelProvider() {return new DataSourceTableLabelProvider();} /** @return the TableViewer for the view */ public TableViewer tableViewer() {return viewer;} /** @return headers of columns in the view */ public Vector<String> columnHeaders() {return columnHeaders;} /** @return the menu item to save the contents of the view */ public Action saveViewContentsAction() {return saveDataSourceSetAction;} /** * The ViewSaver passes back a header Element to the view, which can be filled * with view-specific information * @param doc the Document - needed to create new Elements * @param header the Header element to be filled */ public void fillHeaderElement(Document doc, Element header) { // nothing yet in the header } /** * create an XML file which can be used to re-create this Data source set */ private void doSaveDataSourceSet() { ViewSaver vs = new ViewSaver(this,"Save data source set", "Choose a new file in which to save the data source set"); vs.saveResults(); } //------------------------------------------------------------------------------------------ // Adding a new Data source //------------------------------------------------------------------------------------------ /** * Allow the user to select a mapping set and (if it is a mapping to an XML structure) * an instance document to be queried. * Then create the DataSource object and add it to the table of Data Sources. */ private boolean doAddDataSource() { // reset only for relational data sources String userName = ""; String password = ""; String[] extensions = {"*.mapper"}; String mappingSetPath = FileUtil.getFilePathFromUser(this, extensions, "Select mapping set", false); if (!("".equals(mappingSetPath))) try { // get the mapping set URI mappingSetURI = FileUtil.URIFromPath(mappingSetPath); MappedStructure mapStructure = FileUtil.getMappingSet(mappingSetURI); if (mapStructure != null) { messageChannel mc = new SystemMessageChannel(); XOReader xor = null; boolean carryOn = true; Element XMLRoot = null; // check that this mapping set uses the same class model as others in the Data source set String cmFileName = mapStructure.getClassModelFileName(); if ((classModelFileName() != null) && (!(classModelFileName().equals(cmFileName)))) { String message = "Mappings must use the same class model '" + classModelFileName() + "' as other Data sources, not '" + cmFileName + "'"; MessageDialog.openError(getSite().getShell(), "Mismatch of class models", message); return false; } /* If the mappings are to an XML schema, ask the user for the location of an instance * and attempt to open it. */ if ((mapStructure.getStructureType() == StructureType.XSD)| (mapStructure.getStructureType() == StructureType.V2)) { XMLRoot = getXMLInstance(mapStructure); if (XMLRoot != null) { EPackage classModel = mapStructure.getClassModelRoot(); xor = mapStructure.getXOReader(XMLRoot, classModel, mc); // check that the XML instance conforms to the mapped structure carryOn = true; Vector<StructureMismatch> mismatches = mapStructure.checkInstance(XMLRoot); // show any problems in the Translation Issue View, and check the user wants to carry on if (mismatches.size() > 0) { TranslationIssueView tiv = WorkBenchUtil.getTranslationIssueView(false); if (tiv != null) { Vector<TranslationIssue> mm = new Vector<TranslationIssue>(); for (Iterator<StructureMismatch> it = mismatches.iterator();it.hasNext();) mm.add(it.next()); tiv.showNewResult(mm); tiv.setFocus(); } String message = "There are " + mismatches.size() + " mismatches between the XML instance and the mapped structure;" + " (see Translation Issue View). Do you want to continue?"; carryOn = MessageDialog.openConfirm(getSite().getShell(), "XML Structure Mismatch", message); } } } /* If the mappings are mappings to a relational database, check * the database can be opened; and leave XMLRoot null, as it is created for each query */ else if (mapStructure.getStructureType() == StructureType.RDBMS) { carryOn = false; // see if the database will connect with an empty user name and password try {mapStructure.connectToRDB(userName, password);carryOn = true;} // if not, let the user enter a name and password (but not alter the jdbc connect string) catch (MapperException ex) { DatabaseConnectWizard wizard = new DatabaseConnectWizard(); wizard.init(PlatformUI.getWorkbench(),null); // no selection has been right-clicked WizardDialog dialog = new WizardDialog (PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),wizard); wizard.fixJDBCString(mapStructure.getStructureURL()); dialog.open(); userName = wizard.getUserName(); password = wizard.getPassword(); try {mapStructure.connectToRDB(userName, password);carryOn = true;} catch (Exception e) {} } if (carryOn) { xor = mapStructure.getXOReader(XMLRoot, null, mc); // reader opened with a null XMLRoot instanceLocation = mapStructure.getStructureURL(); // use the jdbc connect string as a location } } // if an XOReader has been successfully created... if ((xor != null) && (carryOn)) { String sourceType = mapStructure.getStructureType().getLiteral(); DataSource qs = new DataSource(xor,mappingSetURI,XMLRoot,sourceType,instanceLocation); // qs.connect(userName,password); dataSources.add(qs); setShortNames(); viewer.add(qs); viewer.setChecked(qs, true); return true; } } } catch (Exception ex) { ex.printStackTrace(); System.out.println(ex.getMessage()); if (ex.getMessage() == null) GenUtil.surprise(ex,"DataSourceView.doAddDataSource"); String message = "Null pointer exception; see console trace for location"; try {if (ex.getMessage() != null) message = ex.getMessage();} catch (Exception e) {} MessageDialog.openError(getSite().getShell(), "Exception opening Data source", message); } return false; } /** * * @return the root of an XML Instance, at a location specified by the user; also sets * its location instanceLocation as a side-effect * @throws MapperException if the XML instance cannot be opened */ private Element getXMLInstance(MappedStructure ms) throws MapperException { Element XMLRoot = null; // get the XML instance, asking the user for its location String[] exts = ms.getExtensions(); String instancePath = FileUtil.getFilePathFromUser(this, exts, "Select instance for data source", false); if (!("".equals(instancePath))) { // this will apply any wrapper 'in' transformations to the input if needed XMLRoot = ms.getXMLRoot(instancePath); // convert from absolute path to platform-relative path URI XMLURI = FileUtil.URIFromPath(instancePath); instanceLocation = XMLURI.toString(); } /* for FHIR data sources, if the user does not define an XML instance, let him * provide the URL of a FHIR server */ else if ((ms.getMappingParameters() != null) && ("com.openMap1.mapper.fhir.FHIRMapper".equals(ms.getMappingParameters().getMappingClass()))) { String fhirServerLocation = WorkBenchUtil.askInput("FHIR server URL","Please provide a URL for a FHIR server"); if (fhirServerLocation != null) { if (fhirServerLocation.startsWith("http")) { if (!fhirServerLocation.endsWith("/")) fhirServerLocation = fhirServerLocation + "/"; instanceLocation = fhirServerLocation; // provide some arbitrary XML root for the reader; it will be changed later Document doc = XMLUtil.makeOutDoc(); XMLRoot = XMLUtil.NSElement(doc, "a", "feed", "http://www.w3.org/2005/Atom"); doc.appendChild(XMLRoot); } else WorkBenchUtil.showMessage("Error", "FHIR server URL should start with 'http'"); } } return XMLRoot; } /** * remove all Data sources currently showing in the view */ public void doClearAllDataSources() { for (Iterator<DataSource> it = dataSources.iterator();it.hasNext();) viewer.remove(it.next()); dataSources = new Vector<DataSource>(); } /** * remove all Data sources which are not currently active */ public void doRemoveInactiveDataSources() { for (Iterator<DataSource> it = dataSources.iterator();it.hasNext();) { DataSource ds = it.next(); /* note that the active flag in a data source is not immediately set when the box is checked, * so we need to look at the viewer to update the active flag on each data source */ ds.setIsActive(viewer.getChecked(ds)); viewer.remove(ds); } Vector<DataSource> newDataSources = new Vector<DataSource>(); for (int i = 0; i < dataSources.size(); i++) if (dataSources.get(i).isActive()) newDataSources.add(dataSources.get(i)); dataSources = newDataSources; setShortNames(); // need to set short names correctly before adding the data sources to the viewer for (int i = 0; i < dataSources.size(); i++) { DataSource ds = dataSources.get(i); viewer.add(ds); viewer.setChecked(ds, true); } } /** * @return the name of the single class model file that is used for all Data sources, * or null if there are no Data sources */ public String classModelFileName() { if (dataSources().size() == 0) return null; return dataSources().get(0).classModelName(); } public Vector<DataSource> getActiveDataSources() { Vector<DataSource> aqs = new Vector<DataSource>(); for (Iterator<DataSource> it = dataSources().iterator();it.hasNext();) { DataSource qs = it.next(); qs.setIsActive(viewer.getChecked(qs)); if (qs.isActive()) aqs.add(qs); } return aqs; } /** * @param code * @return the data source with a given code 'A', 'B' etc. */ public DataSource getDataSourceWithCode(String code) { DataSource ds = null; for (Iterator<DataSource> it = dataSources().iterator();it.hasNext();) { DataSource qs = it.next(); if (qs.getCode().equals(code)) ds = qs; } return ds; } /** * Passing the focus request to the viewer's control. */ public void setFocus() { viewer.getControl().setFocus(); } //------------------------------------------------------------------------------------------ // Defining a FHIR search for all active FHIR data sources //------------------------------------------------------------------------------------------ private void doDefineFHIRSearch() { boolean someFHIRSources = false; String currentFHIRSearch =""; getActiveDataSources(); for (Iterator<DataSource> it = dataSources.iterator();it.hasNext();) { DataSource ds = it.next(); if ((ds.isActive()) && (ds.isNetworkedFHIRSource())) { someFHIRSources = true; if (ds.fhirSearch() != null) currentFHIRSearch = ds.fhirSearch(); } } if (someFHIRSources) { String search = WorkBenchUtil.askInput("FHIR search", "Previous search: '" + currentFHIRSearch + "'"); if (search != null) { for (Iterator<DataSource> it = dataSources.iterator();it.hasNext();) { DataSource ds = it.next(); if ((ds.isActive()) && (ds.isNetworkedFHIRSource())) { ds.setFhirSearch(search); } } } } else WorkBenchUtil.showMessage("Error", "There are no active networked FHIR data sources"); } //------------------------------------------------------------------------------------------ // support for making menu items in the Query editor //------------------------------------------------------------------------------------------ /** * return the Package of the class model of the Data sources in this view; or null */ public EPackage getClassModelPackage() { if (dataSources().size() > 0) try { return dataSources.get(0).getReader().ms().getClassModelRoot(); } catch (MapperException ex) {} return null; } /** * return the URI string of the class model of the Data sources in this view; or null */ public String getClassModelURIString() { if (dataSources().size() > 0) return dataSources.get(0).classModelURIString(); else return null; } /** * @param ec an EClass object (selected in the class model view) * @return true if that class is in the class model * of the Data sources in this Data source set */ public boolean isInDataSourceClassModel(EClass ec) { if (getClassModelPackage() != null) { EPackage thePackage = ec.getEPackage(); return (ModelUtil.getEClass(thePackage, ec.getName()) != null); } else return false; } /** * * @param ec a class in the Data sources class model * @return true if there is some mapping to the class in the * mappings of every active Data source */ public boolean classMappedInAllActiveDataSources(LabelledEClass lec) { boolean mapped = false; if ((isInDataSourceClassModel(lec.eClass())) && (getActiveDataSources().size() > 0)) { mapped = true; for (Iterator<DataSource> it = getActiveDataSources().iterator();it.hasNext();) try { DataSource ds = it.next(); /* For every active data source, there must be some XOReader (imported or * otherwise) that locally represents the class */ mapped = mapped && (lec.getLocalReader(ds) != null); } catch (MapperException ex) {mapped = false;} } return mapped; } /** * * @param ec a class in the Data sources class model * @param propName name of a property of that class * @return true if there is some mapping to the property in the * mappings of every active Data source */ public boolean propertyMappedInAllActiveDataSources(LabelledEClass lec, String propName) { boolean mapped = false; if (isInDataSourceClassModel(lec.eClass())) { String className = lec.getQualifiedClassName(); mapped = true; for (Iterator<DataSource> it = getActiveDataSources().iterator();it.hasNext();) try { DataSource qs = it.next(); XOReader reader = lec.getLocalReader(qs); mapped = mapped && (reader != null) && (reader.representsPropertyLocally(className, propName)); } catch (MapperException ex) {mapped = false;} } return mapped; } /** * * @param ec a class in the Data sources class model * @param roleName role name of an association from that class * @return true if there is some mapping to the association in the * mappings of every active Data source */ public boolean associationMappedInAllActiveDataSources(LabelledEClass lec, String roleName, EClass target) { boolean mapped = false; if (isInDataSourceClassModel(lec.eClass())) { mapped = true; String className = lec.getQualifiedClassName(); String targetClassName = ModelUtil.getQualifiedClassName(target); for (Iterator<DataSource> it = getActiveDataSources().iterator();it.hasNext();) try { DataSource qs = it.next(); XOReader reader = lec.getLocalReader(qs); mapped = mapped && (reader != null) && (reader.representsAssociationRoleLocally (className, roleName, targetClassName)); } catch (MapperException ex) {mapped = false;} } return mapped; } //------------------------------------------------------------------------------------------ // short codes for Data sources //------------------------------------------------------------------------------------------ public void setShortNames() { for (int i = 0; i < dataSources.size(); i++) dataSources.get(i).setCode(shortName(i)); } private String shortName(int i) { String[] names = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R"}; if (i < 18) return names[i]; return names[0]; } //------------------------------------------------------------------------------------------ // restoring the state of the view from an XML file //------------------------------------------------------------------------------------------ private void loadSavedDataSourceSet() { String[] extensions = {"*.xml"}; String viewSavePath = FileUtil.getFilePathFromUser(this, extensions, "Choose a saved Data source view", false); if (!("".equals(viewSavePath))) try { Element root = XMLUtil.readXMLFile(viewSavePath); restoreViewFromDOM(root); } catch (MapperException ex) {MessageDialog.openError(getSite().getShell(), "Exception Loading Data Sources", ex.getMessage());} } /** * restore a Data source view from the root element of * a saved Data source view file * @param viewContents root of the saved Data source view * @throws MapperException if anything goes wrong - for instance if it * is the wrong type of XML file */ public void restoreViewFromDOM(Element viewContents) throws MapperException { String view = viewContents.getAttribute("view"); if (!"Data Sources".equals(view)) throw new MapperException("XML File is not a saved Data source view"); String prefix = "platform:/resource"; doClearAllDataSources(); int row = 0; Element tableContent = XMLUtil.firstNamedChild(viewContents, "TableContent"); if (tableContent != null) for (Iterator<Element> ir = XMLUtil.namedChildElements(tableContent, "row").iterator();ir.hasNext();) { try { Element rowEl = ir.next(); Element typeEl = XMLUtil.firstNamedChild(rowEl,"Type"); String type = typeEl.getTextContent(); Element source = XMLUtil.firstNamedChild(rowEl,"Source"); String sourceLoc = source.getTextContent(); if (sourceLoc.startsWith("/")) sourceLoc = prefix + sourceLoc; Element mappings = XMLUtil.firstNamedChild(rowEl,"Mappings"); String mapLoc = mappings.getTextContent(); if (mapLoc.startsWith("/")) mapLoc = prefix + mapLoc; URI mappingSetURI = URI.createURI(mapLoc); // System.out.println("making source '" + sourceLoc + "'"); DataSource qs = new DataSource(mappingSetURI,type,sourceLoc); qs.setCode(shortName(row)); qs.setIsActive(true); dataSources.add(qs); viewer.add(qs); viewer.setChecked(qs, true); row++; } // if anything goes wrong for any Data source, just miss it out, with this message catch (Exception ex) {System.out.println("Cannot load Data source: " + ex.getMessage());} } } //------------------------------------------------------------------------------------------ // saving and restoring the state of the view between successive sessions //------------------------------------------------------------------------------------------ private static final String TAG_MAPPING_SET_URI = "mappingSetURI"; private static final String TAG_INSTANCE_URI = "instanceURI"; private static final String TAG_SOURCE_TYPE = "sourceType"; private static final String TAG_ACTIVE = "active"; private static final String TAG_TYPE = "DataSource"; public void saveState(IMemento memento) { super.saveState(memento); for (int i = 0; i < viewer.getTable().getItemCount();i++) { IMemento mem = memento.createChild(TAG_TYPE); DataSource qs = (DataSource)viewer.getElementAt(i); mem.putString(TAG_MAPPING_SET_URI, qs.mappingSetURIString()); mem.putString(TAG_INSTANCE_URI, qs.instanceURIString()); mem.putString(TAG_SOURCE_TYPE, qs.sourceType()); if (viewer.getChecked(qs)) mem.putString(TAG_ACTIVE, TAG_ACTIVE); } } /** * re-initialise the model from its state at last closedown * Note the viewer does not exist when this runs. */ public void init(IViewSite site, IMemento memento) throws PartInitException { super.init(site, memento); if (memento != null) { IMemento[] mems = memento.getChildren(TAG_TYPE); for (int i = 0; i < mems.length;i++) { IMemento mem = mems[i]; String instanceURIString = mem.getString(TAG_INSTANCE_URI); String sourceType = mem.getString(TAG_SOURCE_TYPE); try { URI mappingSetURI = URI.createURI(mem.getString(TAG_MAPPING_SET_URI)); DataSource qs = new DataSource(mappingSetURI,sourceType,instanceURIString); dataSources.add(qs); boolean active = false; String act = mem.getString(TAG_ACTIVE); if ((act != null) && (act.equals(TAG_ACTIVE))) active = true; qs.setIsActive(active); } catch (Exception ex) {System.out.println("Could not re-create Data Source for mappings at '" + mem.getString(TAG_MAPPING_SET_URI) + "', XML instance at '" + instanceURIString + "': " + ex.getMessage());} } setShortNames(); } } }