blob: 729d88c7fc4ff57c0f2f1fd2ad585d7e3e4197d6 [file] [log] [blame]
/*******************************************************************************
* <copyright>
*
* Copyright (c) 2005, 2010 SAP AG.
* 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:
* Stefan Dimov - initial API, implementation and documentation
*
* </copyright>
*
*******************************************************************************/
package org.eclipse.jpt.jpadiagrameditor.ui.internal.feature;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import org.eclipse.emf.transaction.RecordingCommand;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.IContext;
import org.eclipse.graphiti.features.context.ICustomContext;
import org.eclipse.graphiti.features.context.IRemoveContext;
import org.eclipse.graphiti.features.context.impl.AddContext;
import org.eclipse.graphiti.features.context.impl.RemoveContext;
import org.eclipse.graphiti.features.custom.AbstractCustomFeature;
import org.eclipse.graphiti.mm.algorithms.RoundedRectangle;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.mm.pictograms.Shape;
import org.eclipse.graphiti.services.Graphiti;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.ui.actions.SelectionDispatchAction;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jpt.jpa.core.JpaFile;
import org.eclipse.jpt.jpa.core.JpaProject;
import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping;
import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit;
import org.eclipse.jpt.jpa.core.resource.java.Annotation;
import org.eclipse.jpt.jpa.core.resource.java.JavaResourceCompilationUnit;
import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentType;
import org.eclipse.jpt.jpa.core.resource.java.OwnableRelationshipMappingAnnotation;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.provider.AddEntityContext;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.provider.IJPAEditorFeatureProvider;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.util.JPAEditorConstants;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.util.JPAEditorUtil;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.util.JPASolver;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.util.JpaArtifactFactory;
import org.eclipse.jpt.common.core.JptResourceModel;
import org.eclipse.jpt.common.utility.model.event.CollectionAddEvent;
import org.eclipse.jpt.common.utility.model.event.CollectionChangeEvent;
import org.eclipse.jpt.common.utility.model.event.CollectionClearEvent;
import org.eclipse.jpt.common.utility.model.event.CollectionRemoveEvent;
import org.eclipse.jpt.common.utility.model.listener.CollectionChangeListener;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
public abstract class RefactorEntityFeature extends AbstractCustomFeature {
protected JavaPersistentType jpt = null;
protected Set<JavaPersistentAttribute> ats = null;
protected boolean hasNameAnnotation = false;
public RefactorEntityFeature(IFeatureProvider fp) {
super(fp);
}
public boolean isAvailable(IContext context) {
if (!(context instanceof ICustomContext))
return false;
ICustomContext ctx = (ICustomContext)context;
PictogramElement pe = ctx.getInnerPictogramElement();
Object bo = getFeatureProvider().getBusinessObjectForPictogramElement(pe);
if (bo instanceof JavaPersistentType) {
jpt = (JavaPersistentType)bo;
hasNameAnnotation = JpaArtifactFactory.instance().hasNameAnnotation(jpt);
return true;
}
if (pe instanceof Shape) {
ContainerShape cs = ((Shape)pe).getContainer();
if (cs == null)
return false;
bo = getFeatureProvider().getBusinessObjectForPictogramElement(cs);
if (bo instanceof JavaPersistentType) {
jpt = (JavaPersistentType)bo;
hasNameAnnotation = JpaArtifactFactory.instance().hasNameAnnotation(jpt);
return true;
}
}
return false;
}
public boolean canExecute(ICustomContext context) {
return true;
}
public void execute(ICustomContext context, SelectionDispatchAction action, ICompilationUnit cu) {
StructuredSelection sel = new StructuredSelection(cu);
final Shape pict = (Shape)getFeatureProvider().getPictogramElementForBusinessObject(jpt);
JavaPersistentType jpt = (JavaPersistentType)getFeatureProvider().
getBusinessObjectForPictogramElement(pict);
final PersistenceUnit pu = JpaArtifactFactory.instance().getPersistenceUnit(jpt);
final Semaphore s = new Semaphore(0);
final JPAProjectListener lsnr = new JPAProjectListener(s);
jpt.getJpaProject().addCollectionChangeListener(JpaProject.JPA_FILES_COLLECTION, lsnr);
ShowBusy showBusy = new ShowBusy(s);
JPASolver.ignoreEvents = true;
final String oldName = jpt.getName();
try {
action.run(sel);
} catch (Exception e) {}
BusyIndicator.showWhile(Display.getCurrent(), showBusy);
jpt.getJpaProject().removeCollectionChangeListener(JpaProject.JPA_FILES_COLLECTION, lsnr);
JPASolver.ignoreEvents = false;
final boolean rename = RenameEntityFeature.class.isInstance(this);
if (!showBusy.isMoved())
return;
TransactionalEditingDomain ted = TransactionUtil.getEditingDomain(pict);
ted.getCommandStack().execute(new RecordingCommand(ted) {
protected void doExecute() {
remapEntity(oldName, pict, pu, rename, lsnr, getFeatureProvider());
}
});
}
public void execute(ICustomContext context, String newName, ICompilationUnit cu, JavaPersistentType jpt) {
final String oldName = jpt.getName();
final Shape pict = (Shape)getFeatureProvider().getPictogramElementForBusinessObject(jpt);
jpt = (JavaPersistentType)getFeatureProvider().
getBusinessObjectForPictogramElement(pict);
final PersistenceUnit pu = JpaArtifactFactory.instance().getPersistenceUnit(jpt);
final Semaphore s = new Semaphore(0);
final JPAProjectListener lsnr = new JPAProjectListener(s);
jpt.getJpaProject().addCollectionChangeListener(JpaProject.JPA_FILES_COLLECTION, lsnr);
ShowBusy showBusy = new ShowBusy(s);
JPASolver.ignoreEvents = true;
JpaArtifactFactory.instance().renameEntityClass(jpt, newName, getFeatureProvider());
BusyIndicator.showWhile(Display.getCurrent(), showBusy);
jpt.getJpaProject().removeCollectionChangeListener(JpaProject.JPA_FILES_COLLECTION, lsnr);
JPASolver.ignoreEvents = false;
TransactionalEditingDomain ted = TransactionUtil.getEditingDomain(pict);
ted.getCommandStack().execute(new RecordingCommand(ted) {
protected void doExecute() {
remapEntity(oldName, pict, pu, true, lsnr, getFeatureProvider());
}
});
}
public static void remapEntity(final String oldName,
final Shape pict,
final PersistenceUnit pu,
final boolean rename,
final JPAProjectListener lsnr,
final IJPAEditorFeatureProvider fp) {
BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
public void run() {
pu.getJpaProject().updateAndWait();
final int x = pict.getGraphicsAlgorithm().getX();
final int y = pict.getGraphicsAlgorithm().getY();
final int width = pict.getGraphicsAlgorithm().getWidth();
final int height = pict.getGraphicsAlgorithm().getHeight();
final ContainerShape cs = Graphiti.getPeService().createContainerShape(fp.getDiagramTypeProvider().getDiagram(),
true);
cs.setVisible(true);
AddContext cont = new AddContext();
cont.setX(x);
cont.setY(y);
cont.setWidth(width);
cont.setHeight(height);
RoundedRectangle rect = AddJPAEntityFeature.createEntityRectangle(cont, cs, fp.getDiagramTypeProvider().getDiagram());
rect.setFilled(true);
IRemoveContext ctx = new RemoveContext(pict);
RemoveJPAEntityFeature ft = new RemoveJPAEntityFeature(fp);
boolean primaryCollapsed = JPAEditorConstants.TRUE_STRING.equals(Graphiti.getPeService().getPropertyValue(pict, JPAEditorConstants.PRIMARY_COLLAPSED));
boolean relationCollapsed = JPAEditorConstants.TRUE_STRING.equals(Graphiti.getPeService().getPropertyValue(pict, JPAEditorConstants.RELATION_COLLAPSED));
boolean basicCollapsed = JPAEditorConstants.TRUE_STRING.equals(Graphiti.getPeService().getPropertyValue(pict, JPAEditorConstants.BASIC_COLLAPSED));
AddEntityContext addCtx = new AddEntityContext(primaryCollapsed, relationCollapsed, basicCollapsed);
String newJPTName = lsnr.getNewJPTName();
JavaPersistentType newJPT = JpaArtifactFactory.instance().getJPT(newJPTName, pu);
if (!JptJpaCorePlugin.discoverAnnotatedClasses(newJPT.getJpaProject().getProject())) {
JPAEditorUtil.createUnregisterEntityFromXMLJob(newJPT.getJpaProject(), oldName);
}
if (rename) {
String tableName = JPAEditorUtil.formTableName(newJPT);
JpaArtifactFactory.instance().setTableName(newJPT, tableName);
}
addCtx.setNewObject(newJPT);
addCtx.setTargetContainer(fp.getDiagramTypeProvider().getDiagram());
addCtx.setX(x);
addCtx.setY(y);
addCtx.setWidth(width);
addCtx.setHeight(height);
AddJPAEntityFeature ft1 = new AddJPAEntityFeature(fp);
ft.remove(ctx);
ft1.add(addCtx);
PictogramElement pe = fp.getPictogramElementForBusinessObject(newJPT);
fp.getDiagramTypeProvider().getDiagramEditor().setPictogramElementForSelection(pe);
Graphiti.getPeService().deletePictogramElement(cs);
JpaArtifactFactory.instance().refreshEntityModel(fp, newJPT);
if (!JptJpaCorePlugin.discoverAnnotatedClasses(newJPT.getJpaProject().getProject())) {
JPAEditorUtil.createRegisterEntityInXMLJob(newJPT.getJpaProject(), newJPTName);
}
}
});
}
protected Diagram getDiagram() {
return getFeatureProvider().getDiagramTypeProvider().getDiagram();
}
public IJPAEditorFeatureProvider getFeatureProvider() {
return (IJPAEditorFeatureProvider)super.getFeatureProvider();
}
class ShowBusy implements Runnable {
private Semaphore s;
boolean moved = false;
ShowBusy(Semaphore s) {
this.s = s;
}
public void run() {
try {
moved = s.tryAcquire(2, 4, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.err.println("Thread interrupted"); //$NON-NLS-1$
e.printStackTrace();
}
}
boolean isMoved() {
return moved;
}
}
public class JPAProjectListener implements CollectionChangeListener {
private Semaphore s = null;
private String newJptName = null;
public JPAProjectListener(Semaphore s) {
this.s = s;
}
public void itemsAdded(CollectionAddEvent event) {
Iterator<?> it = event.getItems().iterator();
Object o = it.next();
JpaFile jpaFile = (JpaFile)o;
JptResourceModel rm = jpaFile.getResourceModel();
if (rm == null)
return;
if (!JavaResourceCompilationUnit.class.isInstance(rm))
return;
JavaResourceCompilationUnit jrcu = (JavaResourceCompilationUnit)rm;
JavaResourcePersistentType jrpt = jrcu.persistentTypes().next();
newJptName = jrpt.getQualifiedName();
s.release();
if ((ats == null) || hasNameAnnotation)
return;
final Iterator<JavaPersistentAttribute> iter = ats.iterator();
Runnable r = new Runnable() {
public void run() {
Hashtable<String, String> atOldToNewName = new Hashtable<String, String>();
Set<JavaPersistentAttribute> newSelfAts = new HashSet<JavaPersistentAttribute>();
while (iter.hasNext()) {
JavaPersistentAttribute at = iter.next();
ICompilationUnit cu = getFeatureProvider().getCompilationUnit((JavaPersistentType) at.getParent());
if (!cu.exists()) {
at = (JavaPersistentAttribute)at.getPersistenceUnit().getPersistentType(newJptName).getAttributeNamed(at.getName());
JavaPersistentAttribute newAt = JpaArtifactFactory.instance().renameAttribute(at, JPAEditorUtil.returnSimpleName(newJptName), newJptName, getFeatureProvider());
atOldToNewName.put(at.getName(), newAt.getName());
newSelfAts.add(newAt);
} else {
JpaArtifactFactory.instance().renameAttribute(at, JPAEditorUtil.returnSimpleName(newJptName), newJptName, getFeatureProvider());
}
}
Iterator<JavaPersistentAttribute> itr = newSelfAts.iterator();
while (itr.hasNext()) {
JavaPersistentAttribute at = itr.next();
JpaArtifactFactory.instance().refreshEntityModel(null, (JavaPersistentType)at.getParent());
JavaAttributeMapping m = at.getMapping();
Annotation mappingAnnotation = m.getMappingAnnotation();
if(mappingAnnotation == null){
JpaArtifactFactory.instance().refreshEntityModel(getFeatureProvider(), (JavaPersistentType)at.getParent());
mappingAnnotation = m.getMappingAnnotation();
}
if (mappingAnnotation == null)
return;
if (OwnableRelationshipMappingAnnotation.class.isInstance(mappingAnnotation)) {
OwnableRelationshipMappingAnnotation ownableMappingAnnotation = (OwnableRelationshipMappingAnnotation)mappingAnnotation;
String oldMappedBy = ownableMappingAnnotation.getMappedBy();
if (oldMappedBy != null) {
String newMappedBy = atOldToNewName.get(oldMappedBy);
if (newMappedBy != null)
ownableMappingAnnotation.setMappedBy(newMappedBy);
}
}
}
}
};
Display.getDefault().asyncExec(r);
}
public void itemsRemoved(CollectionRemoveEvent arg0) {
s.release();
}
public void collectionChanged(CollectionChangeEvent event) {
}
public void collectionCleared(CollectionClearEvent arg0) {}
public String getNewJPTName() {
return newJptName;
}
};
}