| /** |
| * 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.addons.common.resource; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.net.URISyntaxException; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Optional; |
| |
| 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.ui.internal.workbench.E4Workbench; |
| import org.eclipse.e4.ui.internal.workbench.E4XMIResource; |
| import org.eclipse.e4.ui.model.application.MApplication; |
| import org.eclipse.e4.ui.model.application.MApplicationElement; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPerspective; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack; |
| import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder; |
| import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl; |
| import org.eclipse.e4.ui.model.fragment.MFragmentFactory; |
| import org.eclipse.e4.ui.model.fragment.MModelFragment; |
| import org.eclipse.e4.ui.model.fragment.MModelFragments; |
| import org.eclipse.e4.ui.model.fragment.MStringModelFragment; |
| import org.eclipse.e4.ui.workbench.modeling.EModelService; |
| import org.eclipse.e4.ui.workbench.modeling.EPlaceholderResolver; |
| import org.eclipse.emf.common.util.TreeIterator; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.osgi.service.datalocation.Location; |
| import org.eclipse.osbp.vaaclipse.addons.common.api.model.VaaclipseModelUtils; |
| import org.eclipse.osbp.vaaclipse.addons.common.api.resource.ISystemuserModelHandler; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Stateful implementation. |
| */ |
| @SuppressWarnings("restriction") |
| public class SystemuserModelHandler implements ISystemuserModelHandler { |
| |
| /** |
| * A fragment used for the system user settings. Will copied into location |
| * if not available. |
| */ |
| public static final String DEFAULT_SYSTEM_USER_FRAGMENT = "platform:/plugin/org.eclipse.osbp.vaaclipse.addons.perspective/template/systemUserFragment.e4xmi-template"; |
| |
| /** The Constant SYSTEM_USER_FRAGMENT_PROPERTY. */ |
| private static final String SYSTEM_USER_FRAGMENT_PROPERTY = "org.eclipse.osbp.vaaclipse.addons.perspective.systemuser.fragment"; |
| |
| /** The Constant FEATURE__CHILDREN. */ |
| private static final String FEATURE__CHILDREN = UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN |
| .getName(); |
| |
| /** The Constant logger. */ |
| private static final Logger logger = LoggerFactory |
| .getLogger(SystemuserModelHandler.class); |
| |
| /** The use system user. */ |
| private boolean useSystemUser = true; |
| |
| /** The model service. */ |
| @Inject |
| private EModelService modelService; |
| |
| /** The context. */ |
| @Inject |
| private IEclipseContext context; |
| |
| /** The resource set. */ |
| @Inject |
| private ResourceSet resourceSet; |
| |
| /** The instance location. */ |
| @Inject |
| @org.eclipse.e4.core.di.annotations.Optional |
| @Named(E4Workbench.INSTANCE_LOCATION) |
| private Location instanceLocation; |
| |
| /** The system resource. */ |
| private Resource systemResource; |
| |
| /** |
| * Returns the resource for the application model. |
| * |
| * @return the application model resource |
| */ |
| private Resource getApplicationModelResource() { |
| return resourceSet.getResources().get(0); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.vaaclipse.addons.common.api.resource.ISystemuserModelHandler#mergeFragment() |
| */ |
| @Override |
| public void mergeFragment() { |
| if (!useSystemUser) { |
| return; |
| } |
| |
| E4XMIResource applicationResource = (E4XMIResource) getApplicationModelResource(); |
| |
| try { |
| MModelFragments fragmentsContainer = getFragment(); |
| |
| // for the first call check after getFragment() |
| if (!useSystemUser) { |
| return; |
| } |
| |
| List<MModelFragment> fragments = fragmentsContainer.getFragments(); |
| for (MModelFragment fragment : fragments) { |
| List<MApplicationElement> elements = fragment.getElements(); |
| if (elements.size() == 0) { |
| continue; |
| } |
| |
| for (MApplicationElement el : elements) { |
| EObject o = (EObject) el; |
| E4XMIResource r = (E4XMIResource) o.eResource(); |
| |
| if (applicationResource.getIDToEObjectMap().containsKey( |
| r.getID(o))) { |
| continue; |
| } |
| |
| applicationResource.setID(o, r.getID(o)); |
| |
| // Remember IDs of subitems |
| TreeIterator<EObject> treeIt = EcoreUtil.getAllContents(o, |
| true); |
| while (treeIt.hasNext()) { |
| EObject eObj = treeIt.next(); |
| r = (E4XMIResource) eObj.eResource(); |
| applicationResource.setID(eObj, r.getInternalId(eObj)); |
| } |
| } |
| |
| MApplication application = (MApplication) applicationResource |
| .getContents().get(0); |
| merge(application, (MStringModelFragment) fragment); |
| } |
| } finally { |
| unload(); |
| } |
| } |
| |
| /** |
| * Merge. |
| * |
| * @param application |
| * the application |
| * @param fragment |
| * the fragment |
| * @return the list |
| */ |
| public List<MApplicationElement> merge(MApplication application, |
| MStringModelFragment fragment) { |
| MApplicationElement o = VaaclipseModelUtils.findElementById( |
| application, fragment.getParentElementId()); |
| if (o != null) { |
| EStructuralFeature feature = ((EObject) o).eClass() |
| .getEStructuralFeature(fragment.getFeaturename()); |
| if (feature != null) { |
| return VaaclipseModelUtils.merge(o, feature, |
| fragment.getElements(), fragment.getPositionInList()); |
| } |
| |
| } |
| |
| return Collections.emptyList(); |
| } |
| |
| /** |
| * Find fragments. |
| * |
| * @param parentId |
| * the parent id |
| * @param featureName |
| * the feature name |
| * @param fragmentsContainer |
| * the fragments container |
| * @return the list |
| */ |
| protected List<MModelFragment> findFragments(String parentId, |
| String featureName, MModelFragments fragmentsContainer) { |
| final List<MModelFragment> result = new ArrayList<MModelFragment>(); |
| fragmentsContainer |
| .getFragments() |
| .stream() |
| .filter(e -> e instanceof MStringModelFragment) |
| .map(c -> (MStringModelFragment) c) |
| .filter(e -> e.getParentElementId().equals(parentId) |
| && e.getFeaturename().equals(featureName)) |
| .forEach(e -> result.add(e)); |
| return result; |
| } |
| |
| /** |
| * Creates the fragment. |
| * |
| * @param parentId |
| * the parent id |
| * @param featureName |
| * the feature name |
| * @return the m model fragment |
| */ |
| protected MModelFragment createFragment(String parentId, String featureName) { |
| MStringModelFragment fragment = MFragmentFactory.INSTANCE |
| .createStringModelFragment(); |
| fragment.setParentElementId(parentId); |
| fragment.setFeaturename(featureName); |
| return fragment; |
| } |
| |
| /** |
| * Creates the fragment container. |
| * |
| * @return the m model fragments |
| */ |
| protected MModelFragments createFragmentContainer() { |
| MModelFragments container = MFragmentFactory.INSTANCE |
| .createModelFragments(); |
| return container; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.vaaclipse.addons.common.api.resource.ISystemuserModelHandler#addPerspectiveFragment(org.eclipse.e4.ui.model.application.ui.advanced.MPerspectiveStack, org.eclipse.e4.ui.model.application.ui.advanced.MPerspective) |
| */ |
| @Override |
| public void addPerspectiveFragment(MPerspectiveStack parent, |
| MPerspective newPerspective) { |
| |
| if(!useSystemUser) { |
| return; |
| } |
| |
| MModelFragment fragment = null; |
| try { |
| MModelFragments fragmentsContainer = getFragment(); |
| fragment = createPerspectiveFragment(parent, newPerspective); |
| fragmentsContainer.getFragments().add(fragment); |
| |
| persistFragment(fragmentsContainer); |
| } catch (IOException e) { |
| logger.warn("{}", e); |
| } finally { |
| unload(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.vaaclipse.addons.common.api.resource.ISystemuserModelHandler#removePerspectiveFragment(java.lang.String, org.eclipse.e4.ui.model.application.ui.advanced.MPerspective) |
| */ |
| @Override |
| public void removePerspectiveFragment(String parentId, |
| MPerspective perspective) { |
| if (!useSystemUser) { |
| return; |
| } |
| |
| try { |
| MModelFragments container = getFragment(); |
| if (container != null) { |
| removePerspective(parentId, perspective, container); |
| |
| persistFragment(container); |
| } |
| } catch (IOException e) { |
| logger.error("{}", e); |
| } |
| } |
| |
| /** |
| * Removes the perspective. |
| * |
| * @param parentId |
| * the parent id |
| * @param perspective |
| * the perspective |
| * @param fragmentsContainer |
| * the fragments container |
| */ |
| protected void removePerspective(String parentId, MPerspective perspective, |
| MModelFragments fragmentsContainer) { |
| |
| MModelFragment fragment = findFragmentForPerspective(parentId, |
| perspective, fragmentsContainer); |
| if (fragment.getElements().size() > 1) { |
| throw new IllegalArgumentException( |
| "Customized fragments may only contain one element!"); |
| } |
| fragmentsContainer.getFragments().remove(fragment); |
| } |
| |
| /** |
| * Creates the perspective fragment. |
| * |
| * @param parent |
| * the parent |
| * @param newPerspective |
| * the new perspective |
| * @return the m model fragment |
| */ |
| protected MModelFragment createPerspectiveFragment( |
| MPerspectiveStack parent, MPerspective newPerspective) { |
| MModelFragment fragment = createFragment(parent.getElementId(), |
| FEATURE__CHILDREN); |
| |
| MPerspective clone = (MPerspective) modelService.cloneElement( |
| newPerspective, null); |
| EPlaceholderResolver resolver = context.get(EPlaceholderResolver.class); |
| // Re-resolve any placeholder references |
| List<MPlaceholder> phList = modelService.findElements(clone, null, |
| MPlaceholder.class, null); |
| for (MPlaceholder ph : phList) { |
| resolver.resolvePlaceholderRef(ph, |
| modelService.getTopLevelWindowFor(parent)); |
| } |
| fragment.getElements().add(clone); |
| return fragment; |
| } |
| |
| /** |
| * Find fragment for perspective. |
| * |
| * @param parentId |
| * the parent id |
| * @param perspective |
| * the perspective |
| * @param fragmentsContainer |
| * the fragments container |
| * @return the m model fragment |
| */ |
| protected MModelFragment findFragmentForPerspective(String parentId, |
| MPerspective perspective, MModelFragments fragmentsContainer) { |
| List<MModelFragment> fragments = findFragments(parentId, |
| FEATURE__CHILDREN, fragmentsContainer); |
| |
| Optional<MModelFragment> fragment = fragments |
| .stream() |
| .filter(e -> e |
| .getElements() |
| .stream() |
| .filter(c -> c.getElementId().equals( |
| perspective.getElementId())).iterator() |
| .hasNext()).findFirst(); |
| |
| return fragment.isPresent() ? fragment.get() : null; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.osbp.vaaclipse.addons.common.api.resource.ISystemuserModelHandler#persistFragment(org.eclipse.e4.ui.model.fragment.MModelFragments) |
| */ |
| @Override |
| public void persistFragment(MModelFragments mFragments) throws IOException { |
| |
| if (!useSystemUser) { |
| return; |
| } |
| |
| if (!validateFragement(mFragments)) { |
| throw new IllegalStateException( |
| "Fragments are not configured properly."); |
| } |
| |
| ensureSystemUserFragment(); |
| |
| File saveLocation = getSystemUserFragmentLocation(); |
| if (saveLocation.exists()) { |
| Resource toSave = resourceSet.getResource( |
| URI.createFileURI(saveLocation.getAbsolutePath()), true); |
| toSave.getContents().clear(); |
| toSave.getContents().add((EObject) mFragments); |
| toSave.save(null); |
| toSave.unload(); |
| } |
| } |
| |
| /** |
| * Validate fragement. |
| * |
| * @param mFragments |
| * the m fragments |
| * @return true, if successful |
| */ |
| protected boolean validateFragement(MModelFragments mFragments) { |
| java.util.Optional<MModelFragment> result = mFragments.getFragments() |
| .stream().filter(e -> e.getElements().size() > 1).findFirst(); |
| if (result.isPresent()) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Gets the fragment. |
| * |
| * @return the fragment |
| */ |
| protected MModelFragments getFragment() { |
| |
| ensureSystemUserFragment(); |
| |
| // Then load the customized user fragments |
| // |
| File systemLocation = getSystemUserFragmentLocation(); |
| if (systemLocation.exists()) { |
| systemResource = resourceSet.getResource( |
| URI.createFileURI(systemLocation.getAbsolutePath()), true); |
| MModelFragments result = (MModelFragments) systemResource |
| .getContents().get(0); |
| return result; |
| } |
| |
| return null; |
| } |
| |
| /** |
| * Unload the system resource. After merge it will be damaged since |
| * containment references are broken. |
| */ |
| protected void unload() { |
| if (systemResource != null) { |
| systemResource.unload(); |
| } |
| } |
| |
| /** |
| * Ensures that the system user fragment exists in workbench location. |
| */ |
| protected void ensureSystemUserFragment() { |
| // check the system user file |
| File systemUserFile = getSystemUserFragmentLocation(); |
| if (!systemUserFile.exists()) { |
| try { |
| String uri = (String) context |
| .get(SYSTEM_USER_FRAGMENT_PROPERTY); |
| if (uri == null) { |
| uri = DEFAULT_SYSTEM_USER_FRAGMENT; |
| } |
| |
| Resource sysuserFragment = resourceSet.getResource( |
| URI.createURI(uri), true); |
| // copy model |
| sysuserFragment.setURI(URI.createFileURI(systemUserFile |
| .getAbsolutePath())); |
| try { |
| sysuserFragment.save(null); |
| } catch (IOException e) { |
| logger.warn("{}", e); |
| } |
| |
| // unload the fragment |
| sysuserFragment.unload(); |
| resourceSet.getResources().remove(sysuserFragment); |
| } catch (Exception e) { |
| useSystemUser = false; |
| logger.debug("SystemUserFragment not in use"); |
| } |
| } |
| } |
| |
| /** |
| * Gets the system user fragment location. |
| * |
| * @return the system user fragment location |
| */ |
| private File getSystemUserFragmentLocation() { |
| File workbenchData = new File(getBaseLocation(), |
| "systemUserFragment.e4xmi"); //$NON-NLS-1$ |
| return workbenchData; |
| } |
| |
| /** |
| * Gets the base location. |
| * |
| * @return the base 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.e4.workbench"); //$NON-NLS-1$ |
| return baseLocation; |
| } |
| |
| } |