blob: 7182f0f690e5da6cc0ebdbb727d7dc843b015af6 [file] [log] [blame]
/**
*
* Copyright (c) 2011, 2016 - 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:
* Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
*/
package org.eclipse.osbp.ide.core.ui.softwarefactory.extender;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.emf.common.util.URI;
import org.eclipse.osbp.ide.core.ui.softwarefactory.builder.OSBP2Builder;
import org.eclipse.osbp.ide.core.ui.softwarefactory.extender.IModelExtenderProvider.Event.Listener;
import org.eclipse.xtext.builder.builderState.IBuilderState;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.IResourceDescription;
import org.eclipse.xtext.resource.IResourceDescription.Delta;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@Singleton
public class ModelExtenderEventSource implements IModelExtenderProvider.Event.Source, IResourceDescription.Event.Listener {
private CopyOnWriteArraySet<IModelExtenderProvider.Event.Listener> listenerList;
private ConcurrentHashMap<IModelExtenderProvider.Event.Listener, ConcurrentHashMap<String, ModelInstanceDescription>> packageDeltaMap;
private Set<String> pending = new CopyOnWriteArraySet<String>();
/** The adapter. */
private IModelExtenderAdapter adapter;
@Inject
protected IWorkspace workspace;
@Inject
private IBuilderState builderState;
@Inject
public ModelExtenderEventSource() {
listenerList = new CopyOnWriteArraySet<IModelExtenderProvider.Event.Listener>();
packageDeltaMap = new ConcurrentHashMap<IModelExtenderProvider.Event.Listener, ConcurrentHashMap<String, ModelInstanceDescription>>();
}
@Override
public void addListener(IModelExtenderProvider.Event.Listener listener) {
packageDeltaMap.put(listener, new ConcurrentHashMap<String, ModelInstanceDescription>());
listenerList.add(listener);
// request builderstate notification
builderState.addListener(this);
}
@Override
public void removeListener(IModelExtenderProvider.Event.Listener listener) {
listenerList.remove(listener);
packageDeltaMap.remove(listener);
builderState.removeListener(this);
}
public ConcurrentHashMap<IModelExtenderProvider.Event.Listener, ConcurrentHashMap<String, ModelInstanceDescription>> getPackageDeltaMap() {
return packageDeltaMap;
}
public void setPackageDeltaMap(
ConcurrentHashMap<IModelExtenderProvider.Event.Listener, ConcurrentHashMap<String, ModelInstanceDescription>> packageDeltaMap) {
this.packageDeltaMap = packageDeltaMap;
}
public Collection<IModelExtenderProvider.Event.Listener> getListenerList() {
return listenerList;
}
@Override
public void notifyListeners(IModelExtenderProvider.Event event) {
if (event == null)
throw new IllegalArgumentException("event may not be null");
for (IModelExtenderProvider.Event.Listener listener : listenerList) {
listener.modelExtended(event);
}
}
@Override
public void addExtension(Listener listener, BaseExtender baseExtender) throws Exception {
addExtension(listener, baseExtender.getExtension(), baseExtender.getAdapter());
}
@Override
public void addExtension(IModelExtenderProvider.Event.Listener listener, String extension, IModelExtenderAdapter adapter) throws Exception {
this.adapter = adapter;
ModelInstanceDescription pd = new ModelInstanceDescription();
String projectPath = adapter.getModelPath(extension);
pd.setModelPath(projectPath);
if (projectPath != null) {
URI path = URI.createFileURI(projectPath);
// find the bundle segment
for (IProject proj : workspace.getRoot().getProjects()) {
String modelFile = null;
for (int i = 0; i < path.segmentCount(); i++) {
if (modelFile != null) {
modelFile += "/" + path.segment(i);
}
if (proj.getName().equals(path.segment(i))) {
pd.setProject(proj);
modelFile = "";
}
}
if (modelFile != null) {
pd.setModelFile(modelFile);
break;
}
}
try {
pd.setModelURI(URI.createPlatformResourceURI(pd.getProject().getFullPath().toString() + pd.getModelFile(), false));
} catch (NullPointerException npe){
throw new Exception("No project found for the extension: '" + extension + "'. \nPossible reasons: \n1. Incorrect path to the model. \n2. Not existing bundle containing this model.");
}
}
packageDeltaMap.get(listener).put(extension, pd);
}
@Override
public Map<String, ModelInstanceDescription> getModelInstanceDescriptionMap(IModelExtenderProvider.Event.Listener listener) {
return packageDeltaMap.get(listener);
}
@Override
public Set<String> getPending() {
return pending;
}
@Override
public void descriptionsChanged(org.eclipse.xtext.resource.IResourceDescription.Event event) {
Map<String, IResourceDescription> toBeRebuilt = new HashMap<String, IResourceDescription>();
for (Delta delta : event.getDeltas()) {
if ((delta.haveEObjectDescriptionsChanged() && delta.getNew() != null) || authorizationChanged(delta)) {
toBeRebuilt.put(delta.getUri().fileExtension(), delta.getNew());
}
}
for (String extension : toBeRebuilt.keySet()) {
for (Listener listener : getListenerList()) {
Map<String, ModelInstanceDescription> modelInstanceDecriptionMap = getModelInstanceDescriptionMap(listener);
if (modelInstanceDecriptionMap.containsKey(extension)) {
if (modelInstanceDecriptionMap.get(extension).isDone()) {
if (!modelInstanceDecriptionMap.get(extension).isBuilt()) {
modelInstanceDecriptionMap.get(extension).setResourceDescription(toBeRebuilt.get(extension));
if (!contains(extension)) {
pending.add(extension);
}
}
}
}
}
}
}
boolean authorizationChanged(Delta delta) {
if (delta.getUri().fileExtension().contains(OSBP2Builder.AUTHORIZATION_MODEL_EXTENSION)) {
return (contains(delta.getNew().getImportedNames()) && !contains(delta.getOld().getImportedNames()));
}
return false;
}
boolean contains(Iterable<QualifiedName> iterable) {
String identifier = adapter.getIdentifier().toLowerCase();
for (QualifiedName qn : iterable) {
boolean idFound = qn.getLastSegment().contains(identifier);
if (idFound)
return idFound;
}
return false;
}
boolean contains(String extension) {
for (String ext : pending) {
if (ext.equals(extension)) {
return true;
}
}
return false;
}
}