package com.openMap1.mapper.actions;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.ui.IWorkbenchPart;
import com.openMap1.mapper.core.MapperException;
import com.openMap1.mapper.presentation.MapperEditorPlugin;
import com.openMap1.mapper.structures.StructureDefinition;
import com.openMap1.mapper.util.FileUtil;
import com.openMap1.mapper.util.ModelUtil;
import com.openMap1.mapper.ElementDef;
import com.openMap1.mapper.ImportMappingSet;
import com.openMap1.mapper.MappedStructure;
import com.openMap1.mapper.MapperFactory;
import com.openMap1.mapper.MapperPackage;
import com.openMap1.mapper.MaxMult;
import com.openMap1.mapper.NodeMappingSet;
import com.openMap1.mapper.ObjMapping;
import com.openMap1.mapper.ParameterClass;
import com.openMap1.mapper.ParameterClassValue;
/**
* Action to create a new mapping set for the type of the selected
* Element, and to import the new mapping set on the element.
*
* @author robert
*
*/
public class CreateNewMappingSetForTypeAction extends Action implements IAction {
private StructureDefinition structureDef;
private ElementDef importingElement;
private EditingDomain domain;
private IWorkbenchPart part;
protected MapperPackage mapperPackage = MapperPackage.eINSTANCE;
protected MapperFactory mapperFactory = mapperPackage.getMapperFactory();
public CreateNewMappingSetForTypeAction(IWorkbenchPart part, EditingDomain domain,
ElementDef el, StructureDefinition structureDef){
super("Create and import new Mapping Set of type '" + el.getType() + "'");
this.part = part;
importingElement = el;
this.domain = domain;
this.structureDef = structureDef;
}
public void run()
{
// (1) get a location for the new mapping set from the user
String[] modelExts= {".mapper"};
final String mappingSetPath = FileUtil.getFilePathFromUser(part,modelExts,"Select location for new mapping set",true);
if (mappingSetPath.equals("")) return;
URI mappingSetURI = FileUtil.URIFromPath(mappingSetPath);
// (2) create the new mapping set and save it (probably in the workspace - location chosen by user)
try {
ResourceSet resourceSet = new ResourceSetImpl();
Resource resource = resourceSet.createResource(mappingSetURI);
EObject rootObject = createMappedStructure();
resource.getContents().add(rootObject);
// Save the resource
Map<Object, Object> options = new HashMap<Object, Object>();
options.put(XMLResource.OPTION_ENCODING, "UTF-8");
resource.save(options);
}
catch (Exception exception) {
MapperEditorPlugin.INSTANCE.log(exception);
}
/* (3) Mark the selected element on the current mapping set as importing the new mapping set
* If the importing element has just one class mapping, make it the parameter class value
* of the import. */
ImportMappingSet ims = mapperFactory.createImportMappingSet();
ims.setMappingSetURI(mappingSetURI.toString());
String[] oneMappedClass = singleMappedClass(importingElement);
if (oneMappedClass != null)
{
ParameterClassValue pcv = mapperFactory.createParameterClassValue();
pcv.setMappedPackage(oneMappedClass[0]);
pcv.setMappedClass(oneMappedClass[1]);
pcv.setSubset(oneMappedClass[2]);
ims.getParameterClassValues().add(pcv);
}
SetCommand sc = new SetCommand(domain,importingElement,
MapperPackage.eINSTANCE.getElementDef_ImportMappingSet(),
ims);
domain.getCommandStack().execute(sc);
}
// create the new mapping set
private MappedStructure createMappedStructure() {
// create a bare mapping set
MappedStructure root = mapperFactory.createMappedStructure();
// copy some features from the existing top MappedStructure node
MappedStructure currentRoot = (MappedStructure)ModelUtil.getModelRoot(importingElement);
root.setUMLModelURL(currentRoot.getUMLModelURL());
root.setStructureURL(currentRoot.getStructureURL());
// clone is necessary to stop the new mapping set stealing from this mapping set
root.setMappingParameters(currentRoot.getMappingParameters().cloneNamespacesOnly());
root.setStructureType(currentRoot.getStructureType());
// add an expanded root Element with the correct structure to the new root
root.setTopElementType(importingElement.getType());
try{
ElementDef newStructure = structureDef.typeStructure(importingElement.getType());
newStructure.setExpanded(true);
newStructure.setMaxMultiplicity(MaxMult.ONE);
root.setRootElement(newStructure);
/* if the importing element has just one mapped class, set this class to be the
* parameter class of the imported mapping set, and make one object mapping to
* the class on the root element of the imported mapping set */
String[] oneMappedClass = singleMappedClass(importingElement);
if (oneMappedClass != null)
{
// add the parameter class
ParameterClass pc = MapperFactory.eINSTANCE.createParameterClass();
pc.setPackageName(oneMappedClass[0]);
pc.setClassName(oneMappedClass[1]);
root.getParameterClasses().add(pc);
// add the object mapping, on a NodeMappingSet
NodeMappingSet nms = MapperFactory.eINSTANCE.createNodeMappingSet();
ObjMapping om = MapperFactory.eINSTANCE.createObjMapping();
om.setMappedPackage(oneMappedClass[0]);
om.setMappedClass(oneMappedClass[1]);
om.setSubset(""); // default anyway
nms.getObjectMappings().add(om);
newStructure.setNodeMappingSet(nms);
}
}
catch (MapperException ex){System.out.println(ex.getMessage());}
return root;
}
/**
* @return if the importing Element has a single class mapping on it,
* return an array of the mapped class package name, class name and subset; otherwise return null
*/
public static String[] singleMappedClass(ElementDef importingElement)
{
String[] mappedClass = null;
List<EObject> objMappings = ModelUtil.getEObjectsUnder(importingElement, MapperPackage.eINSTANCE.getObjMapping());
if (objMappings.size() == 1)
{
mappedClass = new String[3];
ObjMapping om = (ObjMapping)objMappings.get(0);
mappedClass[0] = om.getMappedPackage();
mappedClass[1] = om.getMappedClass();
mappedClass[2] = om.getSubset();
}
return mappedClass;
}
}