/* 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.editor.model.remote.scenario;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
import org.flowerplatform.common.CommonPlugin;
import org.flowerplatform.common.util.Pair;
import org.flowerplatform.communication.stateful_service.StatefulServiceInvocationContext;
import org.flowerplatform.communication.tree.GenericTreeContext;
import org.flowerplatform.communication.tree.remote.GenericTreeStatefulService;
import org.flowerplatform.communication.tree.remote.PathFragment;
import org.flowerplatform.communication.tree.remote.TreeNode;
import org.flowerplatform.editor.model.EditorModelPlugin;
import org.flowerplatform.editor.model.remote.DiagramEditableResource;
import org.flowerplatform.editor.model.remote.DiagramEditorStatefulService;
import org.flowerplatform.emf_model.notation.Diagram;
import org.flowerplatform.emf_model.notation.Edge;
import org.flowerplatform.emf_model.notation.NotationFactory;
import org.flowerplatform.emf_model.notation.NotationPackage;
import org.flowerplatform.emf_model.notation.View;
import com.crispico.flower.mp.model.codesync.CodeSyncElement;
import com.crispico.flower.mp.model.codesync.ScenarioElement;
/**
* @author Mariana Gheorghe
*/
public class ScenarioTreeStatefulService extends GenericTreeStatefulService {
private DiagramEditorStatefulService diagramService;
public void setDiagramService(DiagramEditorStatefulService diagramService) {
this.diagramService = diagramService;
}
@Override
public String getInplaceEditorText(
StatefulServiceInvocationContext context,
List<PathFragment> fullPath) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean setInplaceEditorText(
StatefulServiceInvocationContext context, List<PathFragment> path,
String text) {
// TODO Auto-generated method stub
return false;
}
@Override
public String getStatefulClientPrefixId() {
return "Scenario Tree";
}
public Resource getScenariosResource(DiagramEditableResource er) {
String editableResourcePath = er.getEditableResourcePath();
int index = editableResourcePath.lastIndexOf("/");
String scenariosResourcePath = editableResourcePath.substring(0, index);
StringBuilder name = new StringBuilder(editableResourcePath.substring(index));
name.insert(name.indexOf("."), "Scenarios");
scenariosResourcePath += name;
File file = new File(CommonPlugin.getInstance().getWorkspaceRoot(), scenariosResourcePath);
URI scenariosResourceUri = EditorModelPlugin.getInstance().getModelAccessController().getURIFromFile(file);
Resource resource = er.getMainResource().getResourceSet().getResource(scenariosResourceUri, false);
if (resource == null) {
if (file.exists()) {
resource = er.getMainResource().getResourceSet().getResource(scenariosResourceUri, true);
} else {
resource = er.getMainResource().getResourceSet().createResource(scenariosResourceUri);
}
}
return resource;
}
@Override
public Collection<Pair<Object, String>> getChildrenForNode(Object node, TreeNode treeNode, GenericTreeContext context) {
if (node instanceof Class) {
String diagramEditableResourcePath = (String) context.getClientContext().get("diagramEditableResourcePath");
DiagramEditableResource er = (DiagramEditableResource) diagramService.getEditableResource(diagramEditableResourcePath);
Resource resource = getScenariosResource(er);
List<Pair<Object, String>> result = new ArrayList<Pair<Object, String>>();
Diagram diagram = diagramService.getDiagram(er);
for (EObject scenario : resource.getContents()) {
Pair<Object, String> pair = new Pair<Object, String>(scenario, ((CodeSyncElement) scenario).getType());
processScenario(diagram, (ScenarioElement) scenario);
result.add(pair);
}
return result;
} else {
CodeSyncElement cse = (CodeSyncElement) node;
List<Pair<Object, String>> result = new ArrayList<Pair<Object, String>>();
for (CodeSyncElement child : cse.getChildren()) {
Pair<Object, String> pair = new Pair<Object, String>(child, cse.getType());
result.add(pair);
}
return result;
}
}
@Override
public Object getNodeByPath(List<PathFragment> fullPath, GenericTreeContext context) {
if (fullPath == null) {
return ScenarioTreeStatefulService.class;
}
String diagramEditableResourcePath = (String) context.getClientContext().get("diagramEditableResourcePath");
DiagramEditableResource er = (DiagramEditableResource) diagramService.getEditableResource(diagramEditableResourcePath);
Resource resource = getScenariosResource(er);
Object object = resource;
for (PathFragment pathFragment : fullPath) {
Object parent = object;
object = null;
for (Object elt : getChildren(parent)) {
if (((ScenarioElement) elt).getName().equals(pathFragment.getName())) {
object = elt;
}
}
if (object == null) {
return null;
}
}
return object;
}
private List getChildren(Object object) {
if (object instanceof Resource) {
return ((Resource) object).getContents();
} else {
return ((ScenarioElement) object).getChildren();
}
}
protected void processScenario(Diagram diagram, ScenarioElement scenario) {
CodeSyncElement target = scenario.getInteraction();
if (target != null) {
ScenarioElement parent = (ScenarioElement) scenario.eContainer();
if (parent != null) {
CodeSyncElement source = parent.getInteraction();
if (source != null) {
boolean exists = false;
for (Edge existingEgde : diagram.getPersistentEdges()) {
if (existingEgde.getSource().getDiagrammableElement().equals(source) &&
existingEgde.getTarget().getDiagrammableElement().equals(target)) {
exists = true;
}
}
if (!exists) {
// add an egde
Edge edge = NotationFactory.eINSTANCE.createEdge();
View sourceView = getViewForElement(diagram, source);
View targetView = getViewForElement(diagram, target);
if (sourceView != null && targetView != null) {
edge.setSource(sourceView);
edge.setTarget(targetView);
edge.setViewType("scenarioInterraction");
edge.setDiagrammableElement(scenario);
diagram.getPersistentEdges().add(edge);
}
}
}
}
}
for (CodeSyncElement child : scenario.getChildren()) {
processScenario(diagram, (ScenarioElement) child);
}
}
protected View getViewForElement(Diagram diagram, EObject object) {
ECrossReferenceAdapter adapter = ECrossReferenceAdapter.getCrossReferenceAdapter(object);
for (Setting setting : adapter.getNonNavigableInverseReferences(object)) {
if (NotationPackage.eINSTANCE.getView_DiagrammableElement().equals(setting.getEStructuralFeature())) {
View view = (View) setting.getEObject();
return view;
}
}
return null;
}
@Override
public Boolean nodeHasChildren(Object node, TreeNode treeNode, GenericTreeContext context) {
CodeSyncElement cse = (CodeSyncElement) node;
if (cse.getChildren() != null && cse.getChildren().size() > 0) {
return true;
}
return false;
}
@Override
public boolean populateTreeNode(Object source, TreeNode destination, GenericTreeContext context) {
ScenarioElement cse = (ScenarioElement) source;
String label = cse.getName();
if (cse.getNumber() != null) {
label = cse.getNumber() + (cse.getNumber().length() > 0 ? ". " : "") + label;
}
destination.setLabel(label);
return true;
}
@Override
public PathFragment getPathFragmentForNode(Object node, String nodeType, GenericTreeContext context) {
CodeSyncElement cse = (CodeSyncElement) node;
PathFragment fragment = new PathFragment(cse.getName(), cse.getType());
return fragment;
}
@Override
public String getLabelForLog(Object node, String nodeType) {
return node.toString();
}
}