/*******************************************************************************
* Copyright (c) 2006-2009
* Software Technology Group, Dresden University of Technology
*
* 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:
* Software Technology Group - TU Dresden, Germany
* - initial API and implementation
******************************************************************************/
package org.reuseware.coconut.roundtrip.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil.Copier;
import org.reuseware.coconut.compositionprogram.CompositionProgram;
import org.reuseware.coconut.compositionprogram.FragmentInstance;
import org.reuseware.coconut.fragment.Fragment;
import org.reuseware.coconut.id.ID;
import org.reuseware.coconut.resource.ReuseResources;
import org.reuseware.coconut.roundtrip.ICallbackNameChosen;
import org.reuseware.coconut.roundtrip.IConflictResolver;
import org.reuseware.coconut.roundtrip.RoundTripAdapter;
/**
* AbstractHandler implements functionality that is shared by the
* handler for adding, removing and changing elements.
*/
public abstract class AbstractHandler {
private IConflictResolver conflictResolver;
public AbstractHandler(IConflictResolver resolver) {
super();
this.conflictResolver = resolver;
}
public IConflictResolver getConflictResolver() {
return conflictResolver;
}
public abstract void modifyTemporary(RoundTripAdapter adapter);
public void copyFragment(RoundTripAdapter adapter) {
// copy the source fragment and connect the corresponding composition
getConflictResolver().chooseNewNameForCopiedFragment(adapter, new ICallbackNameChosen() {
public void setChosenName(RoundTripAdapter adapter, URI newName) {
saveFragment(adapter, newName);
}
});
}
public void saveFragment(RoundTripAdapter adapter, URI newSourceUFI) {
// modify temporarily and save a copy of the fragment
// to a new UFI
modifyTemporary(adapter);
URI originalUFI = adapter.getOriginalUFI();
saveToNewSourceFragment(originalUFI, newSourceUFI);
// then revert the changes
adapter.undoChanges();
// TODO: I think the following line of code did not do anything useful
// FragmentRegistry.INSTANCE.updateVirtualFragment(adapter.getOriginalUFI());
// TODO implement correction of the composition program
/*
PackageableElement element = ReuseResources.INSTANCE.getElement(
IDUtil.uriToID(adapter.openerUFI));
if (!(element instanceof CompositionProgram)) {
return;
}
CompositionProgram corrCompositionProgram = (CompositionProgram) element;
saveNewInformationToCompositionProgram(corrCompositionProgram,
originalUFI, newSourceUFI);
saveCompositionProgram(corrCompositionProgram);
*/
}
/**
* Method that returns an adapter of type CopiedFromAdapter from a given
* EObject.
*
* @param eObject
* The EObject that holds the Adapter.
* @return Returns the CopiedFromAdapter from the given EObject
*/
protected RoundTripAdapter getAdapter(EObject eObject) {
RoundTripAdapter resultAdapter = null;
Iterator<Adapter> containerAdapter = eObject.eAdapters().iterator();
while (containerAdapter.hasNext()) {
Adapter nextAdapter = containerAdapter.next();
if (nextAdapter instanceof RoundTripAdapter) {
resultAdapter = (RoundTripAdapter) nextAdapter;
break;
}
}
return resultAdapter;
}
/**
* Saves a modified composition program
*
* @param corrCompositionProgram
* The composition program to be saved
*/
protected void saveCompositionProgram(CompositionProgram corrCompositionProgram) {
try {
corrCompositionProgram.eResource().save(null);
} catch (Exception e) {
// TODO show message to the user
e.printStackTrace();
}
}
/**
* Changes the composition program such that the old fragment reference is
* modified to point at the copied fragment.
*
* @param fixedCompositionProgram
* The affected composition program.
* @param originalUFI
* The old fragment UFI.
* @param newSourceUFI
* The UFI of the copied fragment.
*/
// TODO this does not belong here
protected void saveNewInformationToCompositionProgram(
CompositionProgram fixedCompositionProgram,
URI originalUFI, URI newSourceUFI) {
Iterator<FragmentInstance> fragmentInstances = fixedCompositionProgram
.getFragmentInstances().iterator();
while (fragmentInstances.hasNext()) {
FragmentInstance fi = fragmentInstances.next();
if (fi.getUFI().equals(originalUFI.segmentsList())) {
fi.getUFI().clear();
fi.getUFI().addAll(newSourceUFI.segmentsList());
break;
}
}
}
/**
* Saves a copied fragment.
*
* @param newSourceURI
* The new physical URI for the copied model.
* @param copied
* The copied model content.
* @param newDiagrammURI
* The new UFI for the copied diagram. (may be null for textual
* languages)
* @param diagram
* The copied model diagram. (may be null for textual languages)
*/
// TODO this does not belong here
protected void saveNewSourceFragment(URI newSourceURI,
Collection<EObject> copied, URI newDiagrammURI,
Collection<EObject> diagram) {
System.out.println("saveNewSourceFragment(" + newSourceURI + ")");
ResourceSet resourceSet = new ResourceSetImpl();
Resource newFile = resourceSet.createResource(newSourceURI);
newFile.getContents().clear();
newFile.getContents().addAll(copied);
try {
newFile.save(Collections.EMPTY_MAP);
} catch (IOException e) {
// TODO show message to the user
e.printStackTrace();
}
if (diagram == null) {
return;
}
Resource newDiagram = resourceSet.createResource(newDiagrammURI);
newDiagram.getContents().clear();
newDiagram.getContents().addAll(diagram);
try {
newDiagram.save(Collections.EMPTY_MAP);
} catch (IOException e) {
// TODO show message to the user
e.printStackTrace();
}
}
/**
* Copies a source fragment.
*
* @param originalUFI
* The UFI of the original fragment.
* @param newSourceUFI
* UFI where the copied elements should be saved.
*/
// TODO this does not belong here
public void saveToNewSourceFragment(URI originalUFI,
URI newSourceUFI) {
Fragment fragmentInstance = (Fragment) ReuseResources.INSTANCE.getElement(
IDUtil.uriToID(originalUFI));
Copier copier = new Copier();
Collection<EObject> copied = copier.copyAll(fragmentInstance.getContents());
URI diagramURI = null;
Collection<EObject> copiedDiagram = null;
//TODO jj: is newSourceUFI the "Reuseware:" URI or the physical URI? We need a physical URI!
if (fragmentInstance.getDiagrams().size() > 0) {
// EObject copied = copier.copy(frInstance.getContents().get(0));
copiedDiagram = copier.copyAll(fragmentInstance.getDiagrams());
String diagramextension = fragmentInstance.getDiagrams().get(0)
.eResource().getURI().fileExtension();
diagramURI = newSourceUFI.trimFileExtension().appendFileExtension(diagramextension);
}
copier.copyReferences();
saveNewSourceFragment(newSourceUFI, copied, diagramURI, copiedDiagram);
ReuseResources.INSTANCE.register(newSourceUFI);
}
protected List<URI> getCompositionProgramsUsing(URI ufi) {
System.out.println("getCompositionProgramsUsing(" + ufi + ")");
ID all = RepositoryFactory.eINSTANCE.createID();
all = all.append(".*");
List<PackageableElement> elements = ReuseResources.INSTANCE.getByQuery(all);
List<URI> result = new ArrayList<URI>();
for (PackageableElement element : elements) {
if (!(element instanceof CompositionProgram)) {
continue;
}
CompositionProgram cp = (CompositionProgram) element;
for (FragmentInstance fragmentInstance : cp.getFragmentInstances()) {
//TODO target UFI must be logical address!
if (IDUtil.equals(fragmentInstance.getUFIAsID(), ufi)) {
result.add(IDUtil.idToURI(cp.getID()));
}
}
}
System.out.println("getCompositionProgramsUsing(" + ufi + ") : " + result);
return result;
}
/**
* Returns all target fragment URIs of the composition program
* with the given UFI.
*
* @param compositionProgramUFI the UFI of the composition program
* @return a list of URIs of all target fragment
*/
protected List<URI> getTargetsFromCompositionProgram(URI compositionProgramUFI) {
PackageableElement element = ReuseResources.INSTANCE.getElement(IDUtil.uriToID(compositionProgramUFI));
if (!(element instanceof CompositionProgram)) {
return Collections.emptyList();
}
List<URI> result = new ArrayList<URI>();
CompositionProgram cp = (CompositionProgram) element;
for (FragmentInstance fragmentInstance : cp.getFragmentInstances()) {
if (fragmentInstance.isTarget()) {
result.add(IDUtil.idToURI(fragmentInstance.getTargetUFIAsID()));
}
}
return result;
}
/**
* Returns the URIs of all composition programs that create
* a fragment with the given UFI.
*
* @param ufi the UFI of the target fragment
* @return a list of composition program URIs
*/
protected List<URI> getCreatingCompositionPrograms(URI ufi) {
List<URI> result = new ArrayList<URI>();
if (ufi == null) return result;
for (PackageableElement element : ReuseResources.INSTANCE.getRootPackage().getAllElements()) {
if (element instanceof CompositionProgram) {
CompositionProgram cp = (CompositionProgram) element;
for (FragmentInstance fi : cp.getFragmentInstances()) {
boolean isTargetFragment = fi.isTarget();
boolean ufiIsEqual = IDUtil.idToURI(fi.getTargetUFIAsID()).equals(ufi);
if (isTargetFragment && ufiIsEqual) {
result.add(IDUtil.idToURI(cp.getID()));
}
}
}
}
return result;
}
}