blob: 57d1076719fcaace0ed7b6156658aa37bfccc93a [file] [log] [blame]
/**
* Copyright (c) 2011, 2014 - Lunifera GmbH (Gross Enzersdorf, Austria), Loetz GmbH&Co.KG (69115 Heidelberg, Germany)
* 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:
* Florian Pirchner - Initial implementation
*/
package org.eclipse.osbp.vaaclipse.common.ecview;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.ui.internal.workbench.E4Workbench;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
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.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.osbp.ecview.core.common.extender.IECViewCache;
import org.eclipse.osbp.ecview.core.common.model.core.YView;
import org.eclipse.osbp.ecview.core.common.store.IViewStore;
import org.eclipse.osgi.service.datalocation.Location;
@SuppressWarnings("restriction")
public class ViewStore implements IViewStore {
@Inject
IEclipseContext context;
@Inject
@Optional
@Named(E4Workbench.INSTANCE_LOCATION)
private Location instanceLocation;
@Override
public YView getMostRecentView(String userId, String id) {
List<YView> views = getAllViewVersions(userId, id);
if (!views.isEmpty()) {
return views.get(views.size() - 1);
}
IECViewCache service = context.get(IECViewCache.class);
if (service != null) {
YView view = service.getView(id);
if (view != null) {
return EcoreUtil.copy(view);
}
}
return null;
}
public List<YView> getAllViewVersions(String userId, String id) {
ResourceSet rs = new ResourceSetImpl();
List<YView> views = new ArrayList<YView>();
File viewFolder = getUserFolderLocation(userId);
File[] files = viewFolder.listFiles();
if (files != null) {
for (File file : viewFolder.listFiles()) {
if (file.isFile() && file.toString().endsWith(".ecview")
&& file.toString().contains(id)) {
Resource resource = rs.getResource(
URI.createFileURI(file.getAbsolutePath()), true);
views.add((YView) resource.getContents().get(0));
}
}
Collections.sort(views, new VersionComparator());
}
return views;
}
private URI getExportViewURI(String folderPath, String id, String version) {
File viewFile = new File(folderPath, id + "_" + version + ".ecview"); //$NON-NLS-1$
URI viewURI = URI.createFileURI(viewFile.getAbsolutePath());
return viewURI;
}
private URI getViewURI(String userId, String id, String version) {
File viewFile = new File(getUserFolderLocation(userId), id
+ "_" + version + ".ecview"); //$NON-NLS-1$
URI viewURI = URI.createFileURI(viewFile.getAbsolutePath());
return viewURI;
}
private File getUserFolderLocation(String userId) {
File location = getBaseLocation();
location = new File(location, userId); //$NON-NLS-1$
return location;
}
private File getBaseLocation() {
File baseLocation;
try {
baseLocation = new File(URIUtil.toURI(instanceLocation.getURL()));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
baseLocation = new File(baseLocation, ".metadata"); //$NON-NLS-1$
baseLocation = new File(baseLocation, ".plugins"); //$NON-NLS-1$
baseLocation = new File(baseLocation, "org.eclipse.osbp.ecview"); //$NON-NLS-1$
return baseLocation;
}
@Override
public void saveView(String userId, YView yView) {
cleanUp(yView);
String id = yView.getId();
URI viewURI = getViewURI(userId, id, toVersion(yView));
try {
XMIResource resource = new XMIResourceImpl(viewURI);
resource.load(null);
resource.getContents().clear();
resource.getContents().add(yView);
resource.save(null);
} catch (IOException e) {
XMIResource resource = new XMIResourceImpl(viewURI);
resource.getContents().add(yView);
try {
resource.save(null);
} catch (IOException e1) {
throw new RuntimeException(e1);
}
}
}
@Override
public void export(YView yView, String folder, boolean generateDialog) {
cleanUp(yView);
String id = yView.getId();
URI viewURI = getExportViewURI(folder, id, toVersion(yView));
try {
XMIResource resource = new XMIResourceImpl(viewURI);
resource.load(null);
resource.getContents().clear();
resource.getContents().add(yView);
resource.save(null);
} catch (IOException e) {
XMIResource resource = new XMIResourceImpl(viewURI);
resource.getContents().add(yView);
try {
resource.save(null);
} catch (IOException e1) {
throw new RuntimeException(e1);
}
}
if (generateDialog) {
generateDialog(yView, folder);
}
}
/**
* Generates a dialog dsl model file to be used with the specified ecview.
*
* @param yView
* @param folder
*/
protected void generateDialog(YView yView, String folderPath) {
String dialogContent = "package {package} {\n"
+ "\tdialog {viewName} ecview \"{viewId}\"\n" + "}";
dialogContent = dialogContent.replace("{package}", toPackageName(yView));
dialogContent = dialogContent.replace("{viewName}", toViewName(yView));
dialogContent = dialogContent.replace("{viewId}", toViewId(yView));
File file = new File(getExportViewURI(folderPath, yView.getId(),
toVersion(yView)).appendFileExtension("dialog").toFileString());
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
fos.write(dialogContent.getBytes());
} catch (IOException e) {
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
// nothing to do
}
}
}
}
private CharSequence toViewId(YView yView) {
return yView.getViewName();
}
private CharSequence toViewName(YView yView) {
String name = yView.getViewName();
if (name == null || name.equals("")) {
return "DefineMe";
}
return name.contains(".") ? name.substring(name.lastIndexOf(".") + 1)
: name;
}
private CharSequence toPackageName(YView yView) {
String name = yView.getViewName();
if (name == null || name.equals("") || !name.contains(".")) {
return "to.be.defined";
}
return name.substring(0, name.lastIndexOf("."));
}
@Override
public void deleteView(String userId, String id, String version) {
URI viewURI = getViewURI(userId, id, version);
try {
XMIResource resource = new XMIResourceImpl(viewURI);
resource.load(null);
resource.delete(null);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Remove orphan references.
*
* @param yView
*/
private void cleanUp(YView yView) {
boolean dummyResource = false;
Resource resource = yView.eResource();
if (resource == null) {
dummyResource = true;
resource = new XMIResourceImpl(
URI.createURI("/toDetectOrphanedEObjects"));
resource.getContents().add(yView);
}
while (true) {
boolean orphanFound = false;
Map<EObject, Collection<Setting>> crossReferences = EcoreUtil.CrossReferencer
.find(Collections.singletonList(yView));
for (Map.Entry<EObject, Collection<Setting>> entry : crossReferences
.entrySet()) {
EObject orphan = entry.getKey();
if (orphan.eResource() == null) {
orphanFound = true;
Collection<Setting> settings = entry.getValue();
for (Setting setting : settings) {
EObject container = setting.getEObject();
EStructuralFeature containingFeature = setting
.getEStructuralFeature();
// if the feature is required, then the target is not
// prop configured anymore.
// so we also remove the target from its parent
EcoreUtil.remove(setting, orphan);
if (!containingFeature.isMany()
&& containingFeature.isRequired()) {
// remove the container from its parent
removeFromContainer(container);
}
}
}
}
if (!orphanFound) {
break;
}
}
if (dummyResource) {
resource.getContents().clear();
}
}
/**
* Removes the given object from its container. And iterates to the most top
* feature, which is not required anymore.
*
* @param object
*/
private void removeFromContainer(EObject object) {
EStructuralFeature feature = object.eContainingFeature();
EObject container = object.eContainer();
EcoreUtil.remove(object);
if (container != null && !feature.isMany() && feature.isRequired()) {
// remove the container from its parent
removeFromContainer(container);
}
}
private String toVersion(YView yView) {
String version = yView.getVersion() != null ? yView.getVersion()
: "0.0.0";
if (!version.equals(yView.getVersion())) {
yView.setVersion(version);
}
return version;
}
private static class VersionComparator implements Comparator<YView> {
@Override
public int compare(YView o1, YView o2) {
if (o1.getVersion() == null) {
if (o2.getVersion() == null) {
return 0;
} else {
return 1;
}
}
return o1.getVersion().compareTo(o2.getVersion());
}
}
}