/* license-start
*
* Copyright (C) 2008 - 2013 Crispico, <http://www.crispico.com/>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, at <http://www.gnu.org/licenses/>.
*
* Contributors:
* Crispico - Initial API and implementation
*
* license-end
*/
package org.flowerplatform.codesync.remote;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.flowerplatform.codesync.config.extension.AddNewExtension;
import org.flowerplatform.codesync.config.extension.InplaceEditorExtension;
import org.flowerplatform.codesync.config.extension.InplaceEditorParseException;
import org.flowerplatform.common.CommonPlugin;
import org.flowerplatform.common.ied.InplaceEditorException;
import org.flowerplatform.communication.CommunicationPlugin;
import org.flowerplatform.communication.command.DisplaySimpleMessageClientCommand;
import org.flowerplatform.communication.service.ServiceInvocationContext;
import org.flowerplatform.communication.stateful_service.RemoteInvocation;
import org.flowerplatform.editor.model.remote.DiagramEditableResource;
import org.flowerplatform.editor.model.remote.DiagramEditorStatefulService;
import org.flowerplatform.emf_model.notation.CategorySeparator;
import org.flowerplatform.emf_model.notation.Diagram;
import org.flowerplatform.emf_model.notation.Edge;
import org.flowerplatform.emf_model.notation.Node;
import org.flowerplatform.emf_model.notation.NotationFactory;
import org.flowerplatform.emf_model.notation.View;
import com.crispico.flower.mp.codesync.base.CodeSyncPlugin;
import com.crispico.flower.mp.model.codesync.CodeSyncElement;
import com.crispico.flower.mp.model.codesync.CodeSyncFactory;
import com.crispico.flower.mp.model.codesync.Relation;
/**
* @author Mariana Gheorghe
*/
public class CodeSyncDiagramOperationsService1 {
public static final String VIEW = "view";
public static final String PARENT_CODE_SYNC_ELEMENT = "parentCodeSyncElement";
public static final String PARENT_VIEW = "parentView";
public static final String ID = "codeSyncDiagramOperationsService";
public static CodeSyncDiagramOperationsService1 getInstance() {
return (CodeSyncDiagramOperationsService1) CommunicationPlugin.getInstance()
.getServiceRegistry().getService(ID);
}
@RemoteInvocation
public List<CodeSyncElementDescriptor> getCodeSyncElementDescriptors() {
return CodeSyncPlugin.getInstance().getCodeSyncElementDescriptors();
}
@RemoteInvocation
public List<RelationDescriptor> getRelationDescriptors() {
return CodeSyncPlugin.getInstance().getRelationDescriptors();
}
/**
* @return ID of the view pointing to the newly added element.
*/
@RemoteInvocation
public String addNew(ServiceInvocationContext context, String diagramId, String viewIdOfParent, String codeSyncType, Map<String, Object> parameters) {
// create new CodeSyncElement
CodeSyncElement codeSyncElement = CodeSyncOperationsService.getInstance().create(codeSyncType);
return addOnDiagram(context, diagramId, viewIdOfParent, codeSyncElement, parameters);
}
/**
* @author Mariana Gheorghe
* @author Cristina Constantinescu
*/
public String addOnDiagram(ServiceInvocationContext context, String diagramId, String viewIdOfParent, CodeSyncElement codeSyncElement, Map<String, Object> parameters) {
// create view
View parentView = viewIdOfParent == null ? null : getViewById(context.getAdditionalData(), viewIdOfParent);
if (parameters == null) {
parameters = new HashMap<String, Object>();
}
// run all AddNewExtensions
Resource codeSyncMappingResource = getCodeSyncMappingResource(getEditableResource(context.getAdditionalData()));
for (AddNewExtension addNewExtension : CodeSyncPlugin.getInstance().getAddNewExtensions()) {
if (!addNewExtension.addNew(codeSyncElement, parentView, codeSyncMappingResource, parameters)) {
// element created, don't allow other extensions to perform add logic
break;
}
}
CodeSyncElementDescriptor descriptor = CodeSyncPlugin.getInstance().getCodeSyncElementDescriptor(codeSyncElement.getType());
Node view = (Node) parameters.get(VIEW);
// add to diagram
if (parameters.containsKey(PARENT_VIEW)) {
parentView = (View) parameters.get(PARENT_VIEW);
}
if (parentView == null && viewIdOfParent == null) {
parentView = getViewById(context.getAdditionalData(), diagramId);
}
parentView.getPersistentChildren().add(view);
view.setViewType(parentView.getViewType() + "." + codeSyncElement.getType());
// add to parent
if (descriptor.getCreateCodeSyncElement()) { // can create and add codeSyncElement to resource
view.setDiagrammableElement(codeSyncElement);
if (codeSyncElement.eContainer() == null) {
CodeSyncElement parentCodeSyncElement = null;
if (parameters.containsKey(PARENT_CODE_SYNC_ELEMENT)) {
parentCodeSyncElement = (CodeSyncElement) parameters.get(PARENT_CODE_SYNC_ELEMENT);
} else {
parentCodeSyncElement = (CodeSyncElement) parentView.getDiagrammableElement();
}
CodeSyncOperationsService.getInstance().add(parentCodeSyncElement, codeSyncElement);
}
}
// return ID of the view
return view.getIdBeforeRemoval();
}
public List<CodeSyncElementDescriptor> getChildrenCategories(String codeSyncType) {
CodeSyncElementDescriptor parentDescriptor = CodeSyncPlugin.getInstance().getCodeSyncElementDescriptor(codeSyncType);
List<CodeSyncElementDescriptor> result = new ArrayList<CodeSyncElementDescriptor>();
for (CodeSyncElementDescriptor descriptor : CodeSyncPlugin.getInstance().getCodeSyncElementDescriptors()) {
for (String codeSyncTypeCategory : descriptor.getCodeSyncTypeCategories()) {
if (parentDescriptor.getChildrenCodeSyncTypeCategories().contains(codeSyncTypeCategory)) {
boolean alreadyAdded = false;
for (CodeSyncElementDescriptor addedDescriptor : result) {
if (addedDescriptor.getCategory().equals(descriptor.getCategory())) {
alreadyAdded = true;
break;
}
}
if (!alreadyAdded) {
result.add(descriptor);
}
break;
}
}
}
return result;
}
@RemoteInvocation
public void collapseCompartment(ServiceInvocationContext context, String viewId) {
View view = getViewById(context.getAdditionalData(), viewId);
View parentCompartment = (View) view.eContainer();
parentCompartment.getPersistentChildren().remove(view);
}
@RemoteInvocation
public void expandCompartment(ServiceInvocationContext context, String viewId, String category) {
View view = getViewById(context.getAdditionalData(), viewId);
for (CodeSyncElementDescriptor descriptor : getCodeSyncElementDescriptors()) {
if (category.equals(descriptor.getCategory())) {
addCategorySeparator(view, (CodeSyncElement) view.getDiagrammableElement(), descriptor);
break;
}
}
}
/**
* @author Mariana Gheorghe
* @author Cristina Constantinescu
*/
public void addCategorySeparator(View view, CodeSyncElement codeSyncElement, CodeSyncElementDescriptor descriptor) {
CategorySeparator categorySeparator = NotationFactory.eINSTANCE.createCategorySeparator();
categorySeparator.setViewType("categorySeparator");
categorySeparator.setCategory(descriptor.getCategory());
categorySeparator.setNewChildCodeSyncType(descriptor.getCodeSyncType());
String image = descriptor.getIconUrl();
if (image != null) {
String codeSyncPackage = CodeSyncPlugin.getInstance()
.getBundleContext().getBundle().getSymbolicName();
if (!image.startsWith("/")) {
image = "/" + image;
}
image = codeSyncPackage + image;
}
categorySeparator.setNewChildIcon(image);
CodeSyncElementDescriptor viewDescriptor = CodeSyncPlugin.getInstance().getCodeSyncElementDescriptor(codeSyncElement.getType());
int index = 0;
for (View child : view.getPersistentChildren()) {
CodeSyncElement childElement = (CodeSyncElement) child.getDiagrammableElement();
if (childElement == null) {
boolean foundOrderIndex = false;
// CategorySeparator, search for orderIndex in list of children that has this set as category
for (CodeSyncElementDescriptor descr : CodeSyncPlugin.getInstance().getCodeSyncElementDescriptors()) {
for (String codeSyncTypeCategory : descr.getCodeSyncTypeCategories()) {
if (viewDescriptor.getChildrenCodeSyncTypeCategories().contains(codeSyncTypeCategory)) {
if (((CategorySeparator) child).getCategory().equals(descr.getCategory())) {
if (descr.getOrderIndex() <= descriptor.getOrderIndex()) {
index++;
foundOrderIndex = true;
break;
}
}
}
}
if (foundOrderIndex) {
break;
}
}
} else {
CodeSyncElementDescriptor childDescriptor = CodeSyncPlugin.getInstance().getCodeSyncElementDescriptor(childElement.getType());
if (childDescriptor.getOrderIndex() <= descriptor.getOrderIndex()) {
index++;
}
}
}
if (index != 0) {
view.getPersistentChildren().add(index, categorySeparator);
} else {
view.getPersistentChildren().add(categorySeparator);
}
}
/**
* @author Cristina Constantinescu
*/
@RemoteInvocation
public String getInplaceEditorText(ServiceInvocationContext context, String viewId) {
View view = getViewById(context.getAdditionalData(), viewId);
Map<String, Object> parameters = new HashMap<String, Object>();
for (InplaceEditorExtension extension : CodeSyncPlugin.getInstance().getInplaceEditorExtensions()) {
try {
if (!extension.getInplaceEditorText(view, parameters)) {
// the extension provided the right text, so don't continue with the others
break;
}
} catch (InplaceEditorParseException e) {
// the extension had to provide the right text, but something happened
context.getCommunicationChannel().appendOrSendCommand(
new DisplaySimpleMessageClientCommand(
CommonPlugin.getInstance().getMessage("error"),
e.getMessage(),
DisplaySimpleMessageClientCommand.ICON_ERROR));
}
}
if (!parameters.containsKey(InplaceEditorExtension.VIEW_TEXT)) {
throw new RuntimeException("'parameters' doesn't contain key InplaceEditorExtension.VIEW_TEXT!");
}
return (String) parameters.get(InplaceEditorExtension.VIEW_TEXT);
}
/**
* @author Cristina Constantinescu
*/
@RemoteInvocation
public void setInplaceEditorText(ServiceInvocationContext context, String viewId, String text) {
View view = getViewById(context.getAdditionalData(), viewId);
Map<String, Object> parameters = new HashMap<String, Object>();
for (InplaceEditorExtension extension : CodeSyncPlugin.getInstance().getInplaceEditorExtensions()) {
try {
if (!extension.setInplaceEditorText(view, text, parameters)) {
// the extension set the new text, so don't continue with the others
break;
}
} catch (InplaceEditorParseException e) {
// the extension had to set the new text, but something happened
context.getCommunicationChannel().appendOrSendCommand(
new DisplaySimpleMessageClientCommand(
CommonPlugin.getInstance().getMessage("error"),
e.getMessage(),
DisplaySimpleMessageClientCommand.ICON_ERROR));
}
}
}
public void addNewRelation(ServiceInvocationContext context, String type, String sourceViewId, String targetViewId) {
View sourceView = getViewById(context.getAdditionalData(), sourceViewId);
View targetView = getViewById(context.getAdditionalData(), targetViewId);
CodeSyncElement source = (CodeSyncElement) sourceView.getDiagrammableElement();
CodeSyncElement target = (CodeSyncElement) targetView.getDiagrammableElement();
Relation relation = CodeSyncFactory.eINSTANCE.createRelation();
relation.setType(type);
relation.setSource(source);
relation.setTarget(target);
source.getRelations().add(relation);
EObject currentObject = sourceView;
Diagram diagram = null;
while (currentObject != null) {
if (currentObject instanceof Diagram) {
diagram = (Diagram) currentObject;
break;
}
currentObject = currentObject.eContainer();
}
createEdge(relation, sourceView, targetView, diagram);
}
protected Edge createEdge(Relation relation, View source, View target, Diagram diagram) {
Edge edge = NotationFactory.eINSTANCE.createEdge();
edge.setDiagrammableElement(relation);
edge.setSource(source);
edge.setTarget(target);
edge.setViewType("edge");
diagram.getPersistentEdges().add(edge);
return edge;
}
///////////////////////
// Utils
///////////////////////
protected View getViewById(Map<String, Object> context, String viewId) {
return (View) getEditableResource(context).getEObjectById(viewId);
}
public DiagramEditableResource getEditableResource(Map<String, Object> context) {
return (DiagramEditableResource) context.get(DiagramEditorStatefulService.ADDITIONAL_DATA_EDITABLE_RESOURCE);
}
public static Resource getCodeSyncMappingResource(DiagramEditableResource diagramEditableResource) {
ResourceSet resourceSet = diagramEditableResource.getResourceSet();
Object project = CodeSyncPlugin.getInstance().getProjectAccessController().getContainingProjectForFile(diagramEditableResource.getFile());
return CodeSyncPlugin.getInstance().getCodeSyncMapping(project, resourceSet);
}
}