/*
* Copyright (c) 2006, 2009 Borland Software Corporation
*
* 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:
* Artem Tikhomirov (Borland) - initial API and implementation
*/
package org.eclipse.gmf.internal.bridge.wizards.pages;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.gmf.internal.bridge.wizards.strategy.AccessibleClassNodeStrategy;
import org.eclipse.gmf.internal.bridge.wizards.strategy.CompositeStrategy;
import org.eclipse.gmf.internal.bridge.wizards.strategy.Hierarchy;
import org.eclipse.gmf.internal.bridge.wizards.strategy.LeafNodeStrategy;
import org.eclipse.gmf.internal.bridge.wizards.strategy.Strategy;
import org.eclipse.gmf.mappings.FeatureLabelMapping;
import org.eclipse.gmf.mappings.GMFMapFactory;
import org.eclipse.gmf.mappings.LinkMapping;
import org.eclipse.gmf.mappings.Mapping;
import org.eclipse.gmf.mappings.MappingEntry;
import org.eclipse.gmf.mappings.NodeMapping;
import org.eclipse.gmf.mappings.NodeReference;
import org.eclipse.gmf.mappings.TopNodeReference;
/**
* @author artem
*/
public class MapDefFeeder {
private final GraphDefLookup myGraphDefLookup;
private final ToolDefSupplier myToolDefLookup;
private Hierarchy myHierarchy;
private final WizardInput myInputHolder;
private List<EClass> myNodeCandidates;
private List<EObject> myLinkCandidates;
public MapDefFeeder(WizardInput holder, ToolDefSupplier toolDefSupplier) {
assert holder != null;
myInputHolder = holder;
myGraphDefLookup = new GraphDefLookup(holder.getCanvasDef());
myToolDefLookup = toolDefSupplier;
}
protected final Mapping getMapping() {
return myInputHolder.getMapping();
}
public void feedDefaultMapping() {
final Hierarchy hierarchy = getHierarchy();
myNodeCandidates = new UniqueEList<EClass>(hierarchy.getAllClasses());
createNodeFilter().filter(myNodeCandidates, hierarchy);
myLinkCandidates = new LinkedList<EObject>();
createLinkFilter().filter(myLinkCandidates, hierarchy);
myLinkCandidates.addAll(hierarchy.getAccessibleReferences(myNodeCandidates.iterator()));
getMapping().getNodes().clear();
getMapping().getNodes().addAll(nodesFrom(myNodeCandidates));
getMapping().getLinks().clear();
getMapping().getLinks().addAll(linksFrom(myLinkCandidates));
getMapping().getDiagram().setPalette(myInputHolder.getToolDef().getPalette());
}
private Hierarchy getHierarchy() {
if (myHierarchy == null) {
myHierarchy = new Hierarchy(getMapping().getDiagram().getDomainMetaElement());
myHierarchy.collect();
}
return myHierarchy;
}
@SuppressWarnings("unchecked")
private Strategy<EClass> createNodeFilter() {
// TODO add UI and instantiate strategies from descriptors
return new CompositeStrategy<EClass>(new AccessibleClassNodeStrategy(), new LeafNodeStrategy());
}
private Strategy<EObject> createLinkFilter() {
//MergingStrategy?
// default: Accessible, Leaf
return new Strategy<EObject>() {
public String getID() {
throw new UnsupportedOperationException("QuickHack");
}
public void filter(Collection<EObject> soFar, Hierarchy hierarchy) {
Set<EClass> linkCandidates = new HashSet<EClass>(hierarchy.getAccessibleLinkClasses());
for (Iterator<EClass> iter = linkCandidates.iterator(); iter.hasNext();) {
EClass element = iter.next();
if (!hierarchy.isLeaf(element)) {
iter.remove();
}
}
soFar.clear();
soFar.addAll(linkCandidates);
}
};
}
private List<TopNodeReference> nodesFrom(List<EClass> candidates) {
ArrayList<TopNodeReference> rv = new ArrayList<TopNodeReference>(candidates.size());
for (EClass eClass : candidates) {
NodeMapping nm = GMFMapFactory.eINSTANCE.createNodeMapping();
nm.setDomainMetaElement(eClass);
addEditFeature(nm, eClass);
nm.setDiagramNode(myGraphDefLookup.findSuitableNode(nm));
myGraphDefLookup.assignLabels(nm, nm.getDiagramNode());
nm.setTool(myToolDefLookup.findTool(nm));
TopNodeReference tnr = GMFMapFactory.eINSTANCE.createTopNodeReference();
tnr.setContainmentFeature(getHierarchy().nodeBackRef(eClass)); // FIXME [containment] !!!
tnr.setOwnedChild(nm);
rv.add(tnr);
}
return rv;
}
private List<LinkMapping> linksFrom(List<EObject> candidates) {
ArrayList<LinkMapping> rv = new ArrayList<LinkMapping>(candidates.size());
for (EObject next : candidates) {
LinkMapping lm = GMFMapFactory.eINSTANCE.createLinkMapping();
if (next instanceof EClass) {
EClass eClass = (EClass) next;
lm.setDomainMetaElement(eClass);
lm.setContainmentFeature(getHierarchy().linkBackRef(eClass));
addEditFeature(lm, eClass);
lm.setLinkMetaFeature(getHierarchy().getLinkFeature(eClass));
} else {
lm.setLinkMetaFeature((EReference) next);
}
lm.setDiagramLink(myGraphDefLookup.findSuitableLink(lm));
myGraphDefLookup.assignLabels(lm, lm.getDiagramLink());
lm.setTool(myToolDefLookup.findTool(lm));
rv.add(lm);
}
return rv;
}
private void addEditFeature(MappingEntry me, EClass class1) {
for (EAttribute n : class1.getEAllAttributes()) {
// EDataType at = n.getEAttributeType();
// at != null && at.getEPackage() != null && at.getEPackage().getNsURI().equals(EcorePackage.eNS_URI) && at.getName().equals(EcorePackage.eINSTANCE.getEString().getName())
if (EcorePackage.eINSTANCE.getEString().equals(n.getEType())) {
FeatureLabelMapping lm = GMFMapFactory.eINSTANCE.createFeatureLabelMapping();
lm.getFeatures().add(n);
me.getLabelMappings().add(lm);
return;
}
}
}
public NodeReference[] getInitialNodes() {
return nodesFrom(myNodeCandidates).toArray(new NodeReference[0]);
}
public LinkMapping[] getInitialLinks() {
return linksFrom(myLinkCandidates).toArray(new LinkMapping[0]);
}
}