blob: 4d8ce5f44af8e14318e06d9f99ab070235f47d77 [file] [log] [blame]
/*******************************************************************************
* <copyright>
*
* Copyright (c) 2005, 2011 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.impl.LayoutContext;
import org.eclipse.graphiti.features.custom.AbstractCustomFeature;
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.ui.editor.IDiagramContainerUI;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.ui.actions.SelectionDispatchAction;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jpt.common.core.JptResourceModel;
import org.eclipse.jpt.common.core.resource.java.JavaResourceCompilationUnit;
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.jpt.jpa.core.JpaFile;
import org.eclipse.jpt.jpa.core.JpaPreferences;
import org.eclipse.jpt.jpa.core.JpaProject;
import org.eclipse.jpt.jpa.core.context.AttributeMapping;
import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
import org.eclipse.jpt.jpa.core.context.PersistentType;
import org.eclipse.jpt.jpa.core.context.RelationshipMapping;
import org.eclipse.jpt.jpa.core.context.SpecifiedMappedByRelationshipStrategy;
import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.JPADiagramEditorPlugin;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.provider.IJPAEditorFeatureProvider;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.util.GraphicsUpdater;
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.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchSite;
public abstract class RefactorEntityFeature extends AbstractCustomFeature {
protected Set<PersistentAttribute> ats = null;
protected boolean hasEntitySpecifiedName = false;
private static final String REGEX_PATTERN = "(_[\\d]+)*"; //$NON-NLS-1$
public RefactorEntityFeature(IFeatureProvider fp) {
super(fp);
}
@Override
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 PersistentType) {
PersistentType jpt = (PersistentType)bo;
ats = JpaArtifactFactory.instance().getRelatedAttributes(jpt);
hasEntitySpecifiedName = JpaArtifactFactory.instance().hasEntitySpecifiedName(jpt);
return true;
}
if (pe instanceof Shape) {
ContainerShape cs = ((Shape)pe).getContainer();
if (cs == null)
return false;
bo = getFeatureProvider().getBusinessObjectForPictogramElement(cs);
if (bo instanceof PersistentType) {
PersistentType jpt = (PersistentType)bo;
ats = JpaArtifactFactory.instance().getRelatedAttributes(jpt);
hasEntitySpecifiedName = JpaArtifactFactory.instance().hasEntitySpecifiedName(jpt);
return true;
}
}
return false;
}
@Override
public boolean canExecute(ICustomContext context) {
return true;
}
public void execute(ICustomContext context, SelectionDispatchAction action) {
PictogramElement pe = context.getInnerPictogramElement();
final ContainerShape pict = ((Shape)pe).getContainer();
final PersistentType jpt = (PersistentType)getBusinessObjectForPictogramElement(pict);
ICompilationUnit cu = getFeatureProvider().getCompilationUnit(jpt);
StructuredSelection sel = new StructuredSelection(cu);
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;
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) {
@Override
protected void doExecute() {
remapEntity(jpt, pict, pu, rename, lsnr, getFeatureProvider());
}
});
}
public void execute(ICustomContext context, String newName, ICompilationUnit cu, PersistentType originalJPT) {
final Shape pict = (Shape)getFeatureProvider().getPictogramElementForBusinessObject(originalJPT);
final PersistentType jpt = (PersistentType)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);
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) {
@Override
protected void doExecute() {
remapEntity(jpt, pict, pu, true, lsnr, getFeatureProvider());
}
});
}
public void remapEntity(final PersistentType oldJPT,
final Shape pict,
final PersistenceUnit pu,
final boolean rename,
final JPAProjectListener lsnr,
final IJPAEditorFeatureProvider fp) {
BusyIndicator.showWhile(Display.getCurrent(), new Runnable() {
public void run() {
fp.getDiagramTypeProvider().getDiagramBehavior().getDiagramContainer().selectPictogramElements(new PictogramElement[] {});
String newJPTName = lsnr.getNewJPTName();
lsnr.setOldJptName(oldJPT.getSimpleName());
if (!JpaPreferences.getDiscoverAnnotatedClasses(oldJPT.getJpaProject().getProject())) {
JPAEditorUtil.createUnregisterEntityFromXMLJob(oldJPT.getJpaProject(), oldJPT.getName());
JPAEditorUtil.createRegisterEntityInXMLJob(oldJPT.getJpaProject(), newJPTName);
}
PersistentType newJPT = JpaArtifactFactory.instance().getJPT(newJPTName, pu);
if(newJPT == null)
return;
// if (!JpaPreferences.getDiscoverAnnotatedClasses(oldJPT.getJpaProject().getProject())) {
// JPAEditorUtil.createUnregisterEntityFromXMLJob(oldJPT.getJpaProject(), oldJPT.getName());
// JPAEditorUtil.createRegisterEntityInXMLJob(oldJPT.getJpaProject(), newJPTName);
// }
if (rename) {
String tableName = JPAEditorUtil.formTableName(newJPT);
JpaArtifactFactory.instance().setTableName(newJPT, tableName);
}
GraphicsUpdater.updateHeader((ContainerShape)pict, newJPT.getSimpleName());
linkNewElement(oldJPT, pict, fp, newJPT);
for(PersistentAttribute oldAttr : oldJPT.getAttributes()){
PictogramElement attrPict = fp.getPictogramElementForBusinessObject(oldAttr);
if(attrPict != null){
for(PersistentAttribute newAttr : newJPT.getAttributes()){
if(newAttr.getName().equals(oldAttr.getName())){
linkNewElement(oldAttr, attrPict, fp, newAttr);
}
}
}
}
fp.getDiagramTypeProvider().getDiagramBehavior().getDiagramContainer().setPictogramElementForSelection(pict);
IWorkbenchSite ws = ((IDiagramContainerUI)fp.getDiagramTypeProvider().getDiagramBehavior().getDiagramContainer()).getSite();
ICompilationUnit cu = fp.getCompilationUnit(newJPT);
fp.getJPAEditorUtil().formatCode(cu, ws);
}
private void linkNewElement(Object oldBO, PictogramElement pict,
IJPAEditorFeatureProvider fp, Object newBO) {
fp.link((ContainerShape)pict, newBO);
LayoutContext context = new LayoutContext((ContainerShape)pict);
fp.layoutIfPossible(context);
String oldBoKey = fp.getKeyForBusinessObject(oldBO);
if(oldBoKey != null){
fp.remove(oldBoKey);
}
String newBoKey = fp.getKeyForBusinessObject(newBO);
if (fp.getBusinessObjectForKey(newBoKey) == null) {
fp.putKeyToBusinessObject(newBoKey, newBO);
}
}
});
}
@Override
protected Diagram getDiagram() {
return getFeatureProvider().getDiagramTypeProvider().getDiagram();
}
@Override
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) {
JPADiagramEditorPlugin.logError("Thread interrupted", e); //$NON-NLS-1$
}
}
boolean isMoved() {
return moved;
}
}
public class JPAProjectListener implements CollectionChangeListener {
private Semaphore s = null;
private String newJptName = null;
private String oldJptName = 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;
IType type = jrcu.getCompilationUnit().findPrimaryType();
newJptName = type.getFullyQualifiedName();
s.release();
if ((ats == null) || hasEntitySpecifiedName)
return;
final Iterator<PersistentAttribute> iter = ats.iterator();
Runnable r = new Runnable() {
public void run() {
Hashtable<String, String> atOldToNewName = new Hashtable<String, String>();
Set<PersistentAttribute> newSelfAts = new HashSet<PersistentAttribute>();
while (iter.hasNext()) {
PersistentAttribute at = iter.next();
String attributeNamPattern = JPAEditorUtil.decapitalizeFirstLetter(oldJptName) + REGEX_PATTERN;
boolean isSame = at.getName().matches(attributeNamPattern);
if(!isSame)
continue;
PersistentType atParent = (PersistentType) at.getParent();
ICompilationUnit cu = getFeatureProvider().getCompilationUnit(atParent);
if (!cu.exists()) {
at = at.getPersistenceUnit().getPersistentType(newJptName).getAttributeNamed(at.getName());
try {
PersistentAttribute newAt = JpaArtifactFactory.instance().renameAttribute(atParent, at.getName(), JPAEditorUtil.returnSimpleName(newJptName), newJptName, getFeatureProvider());
if(newAt != null) {
atOldToNewName.put(at.getName(), newAt.getName());
newSelfAts.add(newAt);
}
} catch (InterruptedException e) {
JPADiagramEditorPlugin.logError(e);
}
} else {
try {
JpaArtifactFactory.instance().renameAttribute(atParent, at.getName(), JPAEditorUtil.returnSimpleName(newJptName), newJptName, getFeatureProvider());
} catch (InterruptedException e) {
JPADiagramEditorPlugin.logError(e);
}
}
}
Iterator<PersistentAttribute> itr = newSelfAts.iterator();
while (itr.hasNext()) {
PersistentAttribute at = itr.next();
AttributeMapping m = JpaArtifactFactory.instance().getAttributeMapping(at);
if(m instanceof RelationshipMapping){
SpecifiedMappedByRelationshipStrategy mappedByRelationShipStrategy = (SpecifiedMappedByRelationshipStrategy)((RelationshipMapping)m).getRelationship().getStrategy();
String oldMappedBy = mappedByRelationShipStrategy.getMappedByAttribute();
if (oldMappedBy != null) {
String newMappedBy = atOldToNewName.get(oldMappedBy);
if(newMappedBy != null) {
mappedByRelationShipStrategy.setMappedByAttribute(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;
}
public void setOldJptName(String oldJptName) {
this.oldJptName = oldJptName;
}
}
}