/***************************************************************************** * Copyright (c) 2010 CEA LIST. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Camille Letavernier (CEA LIST) camille.letavernier@cea.fr - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.customization.properties.model.xwt.resource; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.util.BasicDiagnostic; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; 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.impl.ResourceImpl; import org.eclipse.gmt.modisco.xml.Root; import org.eclipse.gmt.modisco.xml.resource.GenericXMLResourceImpl; import org.eclipse.m2m.qvt.oml.BasicModelExtent; import org.eclipse.m2m.qvt.oml.ExecutionContextImpl; import org.eclipse.m2m.qvt.oml.ExecutionDiagnostic; import org.eclipse.m2m.qvt.oml.ModelExtent; import org.eclipse.m2m.qvt.oml.TransformationExecutor; import org.eclipse.m2m.qvt.oml.util.Log; import org.eclipse.papyrus.customization.properties.model.xwt.Activator; import org.eclipse.papyrus.customization.properties.model.xwt.format.XMLFormatter; import org.eclipse.papyrus.views.properties.contexts.Context; import org.eclipse.papyrus.views.properties.runtime.ConfigurationManager; import org.eclipse.papyrus.views.properties.ui.CompositeWidget; import org.eclipse.papyrus.views.properties.util.PropertiesUtil; /** * A Resource for representing XWT (XML Widget Toolkit) files * as EObjects. * Resulting EObjects are conform to the Papyrus property view UI Metamodel : * http://www.eclipse.org/papyrus/properties/ui/0.9 * * The resource is based on MoDisco for reading and writing XML, * and on QVTO to go from XML to EMF and vice-versa. * * @author Camille Letavernier * * @see UiPackage */ public class XWTResource extends ResourceImpl { private GenericXMLResourceImpl xmlResource; /** * The "format" option. * * This option is a boolean, which default value is true */ public static final String OPTION_FORMAT = "format"; /** * * Constructs a new XWTResource with the given URI * * @param uri * The resource's URI */ public XWTResource(URI uri) { super(uri); xmlResource = new GenericXMLResourceImpl(uri); } @Override protected void doLoad(InputStream inputStream, Map<?, ?> options) throws IOException { xmlResource.load(inputStream, options); Root root = (Root)xmlResource.getContents().get(0); try { CompositeWidget widget = xmlToUISection(root); if(widget == null) { Activator.log.warn("Cannot load the XWT Widget"); } else { getContents().add(widget); } } catch (Exception ex) { Activator.log.error(ex); } } @Override public void save(Map<?, ?> options) throws IOException { if(options == null || options.isEmpty()) { Map<String, String> optionsMap = new HashMap<String, String>(); optionsMap.put(OPTION_SAVE_ONLY_IF_CHANGED, OPTION_SAVE_ONLY_IF_CHANGED_MEMORY_BUFFER); super.save(optionsMap); } else { super.save(options); } Object formatValue = options.get(OPTION_FORMAT); if(formatValue == null || formatValue == Boolean.TRUE) { if(uri.isPlatform()) { IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uri.toPlatformString(true))); XMLFormatter.format(file); } } } @Override protected void doSave(OutputStream outputStream, Map<?, ?> options) throws IOException { try { if(getContents().isEmpty()) { Activator.log.warn("Cannot save an Empty XWT resource : " + getURI()); return; } Root root = uiSectionToXML((CompositeWidget)getContents().get(0)); xmlResource.getContents().clear(); xmlResource.getContents().add(root); xmlResource.save(outputStream, options); } catch (IOException ex) { Activator.log.error(ex); throw ex; } catch (Exception ex) { Activator.log.error(ex); } } private Collection<Context> findContexts() { Set<Context> rootContexts = new HashSet<Context>(); if(resourceSet == null) { return Collections.emptyList(); } for(Resource resource : resourceSet.getResources()) { if(!resource.getContents().isEmpty() && resource.getContents().get(0) instanceof Context) { Context context = (Context)resource.getContents().get(0); rootContexts.add(context); } } Set<Context> allContexts = new HashSet<Context>(); for(Context context : rootContexts) { allContexts.addAll(PropertiesUtil.getDependencies(context)); } return allContexts; } private CompositeWidget xmlToUISection(Root genericXMLRoot) { URI transformationURI = URI.createPlatformPluginURI(Activator.PLUGIN_ID + "/Transformation/XMLToUI.qvto", true); //$NON-NLS-1$ TransformationExecutor executor = new TransformationExecutor(transformationURI); List<Context> contexts = new LinkedList<Context>(findContexts()); ModelExtent inXml = getModelExtent(genericXMLRoot); ModelExtent inRoot = getModelExtent(ConfigurationManager.instance.getPropertiesRoot()); ModelExtent inContexts = new BasicModelExtent(contexts); ModelExtent outUI = new BasicModelExtent(); ExecutionContextImpl context = new ExecutionContextImpl(); context.setLog(getLogger()); context.setConfigProperty("keepModeling", true); //$NON-NLS-1$ ExecutionDiagnostic result = executor.execute(context, inXml, inRoot, inContexts, outUI); if(result.getSeverity() == org.eclipse.emf.common.util.Diagnostic.OK) { List<EObject> outObjects = outUI.getContents(); Object objectResult = outObjects.get(0); if(!(objectResult instanceof CompositeWidget)) { return null; } return (CompositeWidget)outObjects.get(0); } else { IStatus status = BasicDiagnostic.toIStatus(result); Activator.getDefault().getLog().log(status); Activator.log.error(status.getException()); } return null; } private Log getLogger() { return new Log() { public void log(int level, String message) { Activator.getDefault().getLog().log(new Status(level, Activator.PLUGIN_ID, message)); } public void log(int level, String message, Object param) { log(level, message); } public void log(String message) { log(IStatus.INFO, message); } public void log(String message, Object param) { log(message); } }; } private Root uiSectionToXML(CompositeWidget widget) { URI transformationURI = URI.createPlatformPluginURI(Activator.PLUGIN_ID + "/Transformation/UIToXML.qvto", true); //$NON-NLS-1$ TransformationExecutor executor = new TransformationExecutor(transformationURI); ModelExtent inWidget = getModelExtent(widget); ModelExtent outXML = new BasicModelExtent(); ExecutionContextImpl context = new ExecutionContextImpl(); context.setConfigProperty("keepModeling", true); //$NON-NLS-1$ context.setLog(getLogger()); ExecutionDiagnostic result = executor.execute(context, inWidget, outXML); if(result.getSeverity() == org.eclipse.emf.common.util.Diagnostic.OK) { List<EObject> outObjects = outXML.getContents(); return (Root)outObjects.get(0); } else { IStatus status = BasicDiagnostic.toIStatus(result); Activator.getDefault().getLog().log(status); } return null; } private ModelExtent getModelExtent(EObject source) { if(source == null) { return new BasicModelExtent(); } EList<EObject> objects = new BasicEList<EObject>(); objects.add(source); ModelExtent extent = new BasicModelExtent(objects); return extent; } }