/*******************************************************************************
* Copyright (c) 2011, 2012 Red Hat, Inc.
* All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
*
* @author Ivar Meikas
******************************************************************************/
package org.eclipse.bpmn2.modeler.ui.preferences;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import org.eclipse.bpmn2.Bpmn2Package;
import org.eclipse.bpmn2.modeler.core.preferences.ModelEnablements;
import org.eclipse.bpmn2.modeler.core.runtime.ModelEnablementDescriptor;
import org.eclipse.bpmn2.modeler.core.runtime.TargetRuntime;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.osgi.service.prefs.BackingStoreException;
public class ToolProfilesPreferencesHelper {
private ModelEnablements modelEnablements;
private static HashSet<EClass> elementSet = null;
private TargetRuntime targetRuntime;
private String profileId;
private static boolean enableIdAttribute = false;
private ToolProfilesPreferencesHelper() {
}
public ToolProfilesPreferencesHelper(TargetRuntime rt, String profileId) {
this.targetRuntime = rt;
this.profileId = profileId;
createElementSet();
}
/**
* Create the list of EClasses that are candidates for our enable/disable tree.
* As a first cut, select only top-level classes from the Bpmn2Package, then
* add any classes that were enabled in any of the Target Runtime plugins.
*/
private void createElementSet() {
if (elementSet==null) {
elementSet = new HashSet<EClass>();
Bpmn2Package pkg = Bpmn2Package.eINSTANCE;
// EList<EClassifier> allClassifiers = pkg.getEClassifiers();
// final List<EClass> elements = new ArrayList<EClass>();
// for (EClassifier candidate : allClassifiers) {
// if (candidate instanceof EClass && candidate!=pkg.getDocumentRoot()) {
// boolean add = true;
// for (EClassifier ec : allClassifiers) {
// if (ec!=candidate && ec instanceof EClass) {
// for (EClass superType : ((EClass)ec).getESuperTypes()) {
// if (superType == candidate) {
// add = false;
// break;
// }
// }
// }
// }
// if (add)
// elements.add((EClass)candidate);
// }
// }
// elementSet.addAll(elements);
// for (Class c : Bpmn2FeatureMap.ALL_SHAPES) {
// EClass eclass = (EClass)Bpmn2Package.eINSTANCE.getEClassifier(c.getSimpleName());
// elementSet.add(eclass);
// }
for (EClassifier ec : Bpmn2Package.eINSTANCE.getEClassifiers()) {
if (ec instanceof EClass) {
elementSet.add((EClass)ec);
}
}
// for (TargetRuntime rt : TargetRuntime.createTargetRuntimes()) {
// for (ModelEnablementDescriptor med : rt.getModelEnablementDescriptors()) {
// for (String name : med.getAllEnabled()) {
// int i = name.indexOf("."); //$NON-NLS-1$
// if (i>0)
// name = name.substring(i);
// EClassifier ec = pkg.getEClassifier(name);
// if (ec instanceof EClass && !elementSet.contains(ec)) {
// elementSet.add((EClass)ec);
// }
// }
// }
// }
}
}
public static void setEnableIdAttribute(boolean enabled) {
enableIdAttribute = enabled;
}
public static boolean getEnableIdAttribute() {
return enableIdAttribute;
}
public void setModelEnablements(ModelEnablements me) {
modelEnablements = me;
if (modelEnablements!=null)
modelEnablements.setEnableIdAttribute(enableIdAttribute);
}
public ModelEnablements getModelEnablements() {
return modelEnablements;
}
public void copyModelEnablements(ModelEnablements copyMe) {
if (modelEnablements==null) {
modelEnablements = new ModelEnablements(targetRuntime, profileId);
}
modelEnablements.setEnabledAll(false);
for (String name : copyMe.getAllEnabled()) {
modelEnablements.setEnabled(name, true);
}
}
public void clear() {
if (modelEnablements!=null)
modelEnablements.setEnabledAll(false);
}
public List<ModelEnablementTreeEntry> getAllElements() {
ArrayList<ModelEnablementTreeEntry> ret = new ArrayList<ModelEnablementTreeEntry>();
for (EClass eClass : elementSet) {
// if (eClass.getName().startsWith("StandardLoop"))
// System.out.println();
ModelEnablementTreeEntry entry = new ModelEnablementTreeEntry();
entry.setElement(eClass);
boolean enable = isEnabled(eClass);
entry.setEnabled(enable);
ret.add(entry);
HashSet<EStructuralFeature> possibleFeatures = new HashSet<EStructuralFeature>();
ArrayList<ModelEnablementTreeEntry> children = new ArrayList<ModelEnablementTreeEntry>();
for (EAttribute a : eClass.getEAllAttributes()) {
// anyAttribute is always enabled to support
// extension features.
if (!"anyAttribute".equals(a.getName())) //$NON-NLS-1$
possibleFeatures.add(a);
}
for (EReference a : eClass.getEAllContainments()) {
possibleFeatures.add(a);
}
for (EReference a : eClass.getEAllReferences()) {
possibleFeatures.add(a);
}
// if (enable)
{
for (EStructuralFeature feature : possibleFeatures) {
ModelEnablementTreeEntry child = new ModelEnablementTreeEntry(feature, entry);
enable = isEnabled(eClass, feature);
child.setEnabled(enable);
children.add(child);
}
sortElements(children);
entry.setChildren(children);
}
}
sortElements(ret);
return ret;
}
private ModelEnablementTreeEntry findOrCreateEntry(List<ModelEnablementTreeEntry> entries, ENamedElement elem, ModelEnablementTreeEntry parent) {
ModelEnablementTreeEntry entry = findEntry(entries,elem,parent);
if (entry!=null) {
entry.addFriend(parent);
return entry;
}
return new ModelEnablementTreeEntry(elem, parent);
}
private ModelEnablementTreeEntry findEntry(List<ModelEnablementTreeEntry> entries, ENamedElement elem, ModelEnablementTreeEntry parent) {
for (ModelEnablementTreeEntry entry : entries) {
ModelEnablementTreeEntry thisParent = entry.getParent();
if (thisParent!=null && parent!=null) {
if (thisParent.getElement() == parent.getElement()) {
for (ModelEnablementTreeEntry child : thisParent.getChildren()) {
ENamedElement thisElem = child.getElement();
if (thisElem == elem) {
return child;
}
}
}
}
else if (thisParent==parent) {
if (entry.getElement() == elem)
return entry;
}
else if (thisParent==null) {
ModelEnablementTreeEntry t = findEntry(entry.getChildren(), elem, parent);
if (t!=null)
return t;
}
}
return null;
}
public List<ModelEnablementTreeEntry> getAllExtensionElements(TargetRuntime rt, ModelEnablementDescriptor me, List<ModelEnablementTreeEntry> bpmnEntries) {
// Fetch all of the <modelExtension> extension point elements defined in the Target Runtime plugin.
ArrayList<ModelEnablementTreeEntry> bpmnModelExtensions = new ArrayList<ModelEnablementTreeEntry>();
ModelEnablementTreeEntry bpmnModelExtensionsRoot = new ModelEnablementTreeEntry();
bpmnModelExtensionsRoot.setEnabled(true);
bpmnModelExtensionsRoot.setName(Messages.ToolEnablementPreferences_BPMN_Extensions);
for (Entry<EClass, List<EStructuralFeature>> e : rt.getModelExtensions(1).entrySet()) {
// create a ModelEnablementTreeEntry for extension EClass
EClass eClass = e.getKey();
ModelEnablementTreeEntry entry = new ModelEnablementTreeEntry(eClass, bpmnModelExtensionsRoot);
// fetch its current enablement state
entry.setEnabled(isEnabled(eClass));
// and add it to our list
bpmnModelExtensions.add(entry);
ArrayList<ModelEnablementTreeEntry> children = new ArrayList<ModelEnablementTreeEntry>();
for (EStructuralFeature feature : e.getValue()) {
ModelEnablementTreeEntry child = findOrCreateEntry(bpmnEntries, feature, entry);
// set enablement state of the feature:
// the EClass is that of the parent entry.
child.setEnabled(isEnabled(eClass, feature));
children.add(child);
}
// add the sorted list to the children of this entry parent
sortElements(children);
entry.setChildren(children);
}
sortElements(bpmnModelExtensions);
bpmnModelExtensionsRoot.setChildren(bpmnModelExtensions);
ArrayList<ModelEnablementTreeEntry> runtimeModelExtensions = new ArrayList<ModelEnablementTreeEntry>();
ModelEnablementTreeEntry runtimeModelExtensionsRoot = new ModelEnablementTreeEntry();
runtimeModelExtensionsRoot.setEnabled(true);
runtimeModelExtensionsRoot.setName(Messages.ToolEnablementPreferences_Target_Extensions);
for (Entry<EClass, List<EStructuralFeature>> e : rt.getModelExtensions(2).entrySet()) {
// create a ModelEnablementTreeEntry for extension EClass
EClass eClass = e.getKey();
ModelEnablementTreeEntry entry = new ModelEnablementTreeEntry(eClass, runtimeModelExtensionsRoot);
// fetch its current enablement state
entry.setEnabled(isEnabled(eClass));
// and add it to our list
runtimeModelExtensions.add(entry);
ArrayList<ModelEnablementTreeEntry> children = new ArrayList<ModelEnablementTreeEntry>();
for (EStructuralFeature feature : e.getValue()) {
ModelEnablementTreeEntry child = findOrCreateEntry(bpmnEntries, feature, entry);
// set enablement state of the feature:
// the EClass is that of the parent entry.
child.setEnabled(isEnabled(eClass, feature));
children.add(child);
}
// add the sorted list to the children of this entry parent
sortElements(children);
entry.setChildren(children);
}
sortElements(runtimeModelExtensions);
runtimeModelExtensionsRoot.setChildren(runtimeModelExtensions);
ArrayList<ModelEnablementTreeEntry> allExtensions = new ArrayList<ModelEnablementTreeEntry>();
if (!bpmnModelExtensionsRoot.getChildren().isEmpty())
allExtensions.add(bpmnModelExtensionsRoot);
if (!runtimeModelExtensionsRoot.getChildren().isEmpty())
allExtensions.add(runtimeModelExtensionsRoot);
return allExtensions;
}
private void sortElements(ArrayList<ModelEnablementTreeEntry> ret) {
Collections.sort(ret, new Comparator<ModelEnablementTreeEntry>() {
@Override
public int compare(ModelEnablementTreeEntry o1, ModelEnablementTreeEntry o2) {
return o1.getName().compareToIgnoreCase(o2.getName());
}
});
}
public boolean isEnabled(EClass element) {
if (modelEnablements==null)
return false;
return modelEnablements.isEnabled(element);
}
public boolean isEnabled(String name) {
if (modelEnablements==null)
return false;
return modelEnablements.isEnabled(name);
}
public boolean isEnabled(EClass c, ENamedElement element) {
if (modelEnablements==null)
return false;
return modelEnablements.isEnabled(c.getName(), element.getName());
}
public boolean isEnabled(ModelEnablementTreeEntry entry) {
if (modelEnablements==null)
return false;
return modelEnablements.isEnabled(entry.getPreferenceName());
}
public void setEnabled(ModelEnablementTreeEntry entry, boolean enabled) {
if (modelEnablements!=null) {
modelEnablements.setEnabled(entry.getPreferenceName(), enabled);
}
}
public void importProfile(String path) throws FileNotFoundException, IOException, BackingStoreException {
Properties p = new Properties();
p.load(new FileInputStream(path));
ModelEnablements me = new ModelEnablements(targetRuntime, profileId);
for (Object key : p.keySet()) {
Object value = p.get(key);
if (key instanceof String && value instanceof String) {
boolean enabled = Boolean.parseBoolean((String) value);
me.setEnabled((String) key, enabled);
}
}
}
public void exportProfile(String path) throws BackingStoreException, FileNotFoundException, IOException {
FileWriter fw = new FileWriter(path);
boolean writeXml = path.endsWith(".xml"); //$NON-NLS-1$
List<String> keys = modelEnablements.getAllEnabled();
Collections.sort(keys);
ModelEnablementDescriptor med = targetRuntime.getModelEnablements(profileId);
String profileName = med.getProfileName();
String description = med.getDescription();
if (writeXml) {
fw.write("\t\t<modelEnablement"); //$NON-NLS-1$
fw.write(" runtimeId=\"" + targetRuntime.getId() + "\""); //$NON-NLS-1$ //$NON-NLS-2$
fw.write(" id=\"" + profileId + "\""); //$NON-NLS-1$ //$NON-NLS-2$
fw.write(" profile=\"" + profileName + "\""); //$NON-NLS-1$ //$NON-NLS-2$
fw.write(" description=\"" + description + "\""); //$NON-NLS-1$ //$NON-NLS-2$
fw.write(">\r\n"); //$NON-NLS-1$
fw.write("\t\t\t<disable object=\"all\"/>\r\n"); //$NON-NLS-1$
}
for (String k : keys) {
boolean enable = isEnabled(k);
if (writeXml) {
if (enable) {
if (k.contains(".")) { //$NON-NLS-1$
String a[] = k.split("\\."); //$NON-NLS-1$
fw.write("\t\t\t<enable object=\""+ a[0] + "\" feature=\"" + a[1] + "\"/>\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
}
else
fw.write(k + "=" + enable + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$
}
if (writeXml) {
fw.write("\t</modelEnablement>\r\n"); //$NON-NLS-1$
}
fw.flush();
fw.close();
}
}