blob: 2da00febd6730dd88dac5286cca74e205502e309 [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.ArrayList;
import java.util.HashSet;
import java.util.List;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.context.ICreateContext;
import org.eclipse.graphiti.features.context.impl.CreateContext;
import org.eclipse.graphiti.features.impl.AbstractAddShapeFeature;
import org.eclipse.graphiti.mm.algorithms.Image;
import org.eclipse.graphiti.mm.algorithms.Polyline;
import org.eclipse.graphiti.mm.algorithms.Rectangle;
import org.eclipse.graphiti.mm.algorithms.RoundedRectangle;
import org.eclipse.graphiti.mm.algorithms.Text;
import org.eclipse.graphiti.mm.algorithms.styles.LineStyle;
import org.eclipse.graphiti.mm.algorithms.styles.Orientation;
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.graphiti.util.IPredefinedRenderingStyle;
import org.eclipse.graphiti.util.PredefinedColoredAreas;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IPackageDeclaration;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.core.SourceType;
import org.eclipse.jpt.jpa.core.JpaProject;
import org.eclipse.jpt.jpa.core.context.AttributeMapping;
import org.eclipse.jpt.jpa.core.context.java.JavaMappedSuperclass;
import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.JPADiagramEditorPlugin;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.i18n.JPAEditorMessages;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.modelintegration.util.ModelIntegrationUtil;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.provider.IAddEntityContext;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.provider.IJPAEditorFeatureProvider;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.provider.JPAEditorImageProvider;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.util.GraphicsUpdater;
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.JpaArtifactFactory;
import org.eclipse.jpt.jpadiagrameditor.ui.internal.util.JPAEditorConstants.ShapeType;
@SuppressWarnings({ "restriction" })
public class AddJPAEntityFeature extends AbstractAddShapeFeature {
private IPeUtilFacade facade;
private static ContainerShape primaryShape;
private static ContainerShape relationShape;
private static ContainerShape basicShape;
public AddJPAEntityFeature(IFeatureProvider fp) {
super(fp);
facade = new PeUtilFacade();
}
public AddJPAEntityFeature(IFeatureProvider fp, IPeUtilFacade facade) {
super(fp);
this.facade = facade;
}
public boolean canAdd(IAddContext context) {
Object newObj = context.getNewObject();
if (newObj instanceof JavaPersistentType) {
if (context.getTargetContainer() instanceof Diagram) {
JavaPersistentType jpt = (JavaPersistentType) newObj;
return checkJPTForAdding(jpt);
}
} else if (newObj instanceof ICompilationUnit) {
if (context.getTargetContainer() instanceof Diagram) {
ICompilationUnit cu = (ICompilationUnit) newObj;
JavaPersistentType jpt = JPAEditorUtil.getJPType(cu);
return checkJPTForAdding(jpt);
}
} if (newObj instanceof SourceType) {
if (context.getTargetContainer() instanceof Diagram) {
ICompilationUnit cu = ((SourceType)newObj).getCompilationUnit();
JavaPersistentType jpt = JPAEditorUtil.getJPType(cu);
return checkJPTForAdding(jpt);
}
}
return false;
}
private boolean checkJPTForAdding(JavaPersistentType jpt) {
if (jpt == null)
return false;
PictogramElement[] pictograms = getFeatureProvider()
.getAllPictogramElementsForBusinessObject(jpt);
JpaProject proj = ModelIntegrationUtil.getProjectByDiagram(getDiagram().getName());
if (proj != null)
if (proj != jpt.getJpaProject())
return false;
return (pictograms == null) || (pictograms.length == 0);
}
@Override
public IJPAEditorFeatureProvider getFeatureProvider() {
return (IJPAEditorFeatureProvider) super.getFeatureProvider();
}
public PictogramElement add(IAddContext context) {
IJPAEditorFeatureProvider fp = getFeatureProvider();
Object newObj = context.getNewObject();
JavaPersistentType jpt = null;
if (newObj instanceof JavaPersistentType) {
jpt = (JavaPersistentType) newObj;
if (jpt.getMapping() instanceof JavaMappedSuperclass) {
jpt = createEntityFromExistingMappedSuperclass(fp, jpt);
}
} else if (newObj instanceof ICompilationUnit) {
ICompilationUnit cu = (ICompilationUnit) newObj;
jpt = JPAEditorUtil.getJPType(cu);
if (jpt.getMapping() instanceof JavaMappedSuperclass) {
jpt = createEntityFromExistingMappedSuperclass(fp, jpt);
}
} else if (newObj instanceof SourceType) {
ICompilationUnit cu = ((SourceType)newObj).getCompilationUnit();
jpt = JPAEditorUtil.getJPType(cu);
}
final Diagram targetDiagram = (Diagram) context.getTargetContainer();
ContainerShape entityShape = facade.createContainerShape(targetDiagram, true);
createEntityRectangle(context, entityShape,
this.getFeatureProvider().getDiagramTypeProvider().getDiagram());
link(entityShape, jpt);
Shape shape = Graphiti.getPeService().createShape(entityShape, false);
Polyline headerBottomLine = Graphiti.getGaService().createPolyline(shape, new int[] { 0,
30, JPAEditorConstants.ENTITY_WIDTH, 30 });
headerBottomLine
.setForeground(manageColor(JPAEditorConstants.ENTITY_BORDER_COLOR));
headerBottomLine.setLineWidth(JPAEditorConstants.ENTITY_BORDER_WIDTH);
addHeader(jpt, entityShape, JPAEditorConstants.ENTITY_WIDTH);
createCompartments(context, jpt, entityShape);
fillCompartments(jpt,entityShape);
String key = fp.getKeyForBusinessObject(jpt);
if (fp.getBusinessObjectForKey(key) == null)
fp.putKeyToBusinessObject(key, jpt);
Graphiti.getPeService().createChopboxAnchor(entityShape);
entityShape.setVisible(true);
layoutPictogramElement(entityShape);
UpdateAttributeFeature updateFeature = new UpdateAttributeFeature(fp);
updateFeature.reconnect(jpt);
return entityShape;
}
private JavaPersistentType createEntityFromExistingMappedSuperclass(
IJPAEditorFeatureProvider fp, JavaPersistentType jpt) {
ICreateContext cont = new CreateContext();
String packageName = null;
try {
packageName = getMappedSuperclassPackageDeclaration(fp, jpt,
packageName);
} catch (JavaModelException e) {
JPADiagramEditorPlugin.logError(e);
}
boolean hasPrimaryKey = hasMappedSuperclassPrimaryKeyAttribute(jpt);
CreateJPAEntityFeature createFeature = new CreateJPAEntityFeature(fp,
true, jpt.getName(), packageName, hasPrimaryKey);
Object[] objects = createFeature.create(cont);
if (objects.length != 0) {
Object obj = objects[0];
if (obj instanceof JavaPersistentType) {
jpt = (JavaPersistentType) obj;
}
}
return jpt;
}
private boolean hasMappedSuperclassPrimaryKeyAttribute(
JavaPersistentType jpt) {
for (AttributeMapping map : ((JavaMappedSuperclass) jpt.getMapping()).getAllAttributeMappings()) {
if (map.getPrimaryKeyColumnName() != null) {
return true;
}
}
return false;
}
private String getMappedSuperclassPackageDeclaration(
IJPAEditorFeatureProvider fp, JavaPersistentType jpt,
String packageName) throws JavaModelException {
IPackageDeclaration[] packages = fp.getCompilationUnit(jpt)
.getPackageDeclarations();
if (packages.length > 0) {
IPackageDeclaration packageDecl = packages[0];
packageName = packageDecl.getElementName();
}
return packageName;
}
private void createCompartments(IAddContext context, JavaPersistentType jpt,
ContainerShape entityShape) {
primaryShape = createCompartmentRectangle(entityShape, JPAEditorConstants.ENTITY_MIN_HEIGHT, JPAEditorMessages.AddJPAEntityFeature_primaryKeysShape);
relationShape = createCompartmentRectangle(entityShape, GraphicsUpdater.getNextCompartmentY(primaryShape) + JPAEditorConstants.SEPARATOR_HEIGHT,
JPAEditorMessages.AddJPAEntityFeature_relationAttributesShapes);
basicShape = createCompartmentRectangle(entityShape, GraphicsUpdater.getNextCompartmentY(relationShape) + JPAEditorConstants.SEPARATOR_HEIGHT, JPAEditorMessages.AddJPAEntityFeature_basicAttributesShapes);
if (IAddEntityContext.class.isInstance(context)) {
IAddEntityContext entityContext = (IAddEntityContext) context;
GraphicsUpdater.setCollapsed(primaryShape, entityContext.isPrimaryCollapsed());
GraphicsUpdater.setCollapsed(basicShape, entityContext.isBasicCollapsed());
GraphicsUpdater.setCollapsed(relationShape, entityContext.isRelationCollapsed());
} else {
GraphicsUpdater.setCollapsed(primaryShape, false);
GraphicsUpdater.setCollapsed(basicShape, false);
GraphicsUpdater.setCollapsed(relationShape, false);
}
}
private void fillCompartments(JavaPersistentType jpt, ContainerShape entityShape) {
String[] primaryKeyAnnotations = new String[] {JPAEditorConstants.ANNOTATION_ID, JPAEditorConstants.ANNOTATION_EMBEDDED_ID};
for(String annotation : primaryKeyAnnotations){
addCompartmentChildren(primaryShape, jpt, annotation);
}
String[] relationAnnotations = new String[] {JPAEditorConstants.ANNOTATION_MANY_TO_MANY,
JPAEditorConstants.ANNOTATION_MANY_TO_ONE, JPAEditorConstants.ANNOTATION_ONE_TO_MANY,
JPAEditorConstants.ANNOTATION_ONE_TO_ONE};
for(String annotation : relationAnnotations){
addCompartmentChildren(relationShape, jpt, annotation);
}
addBasicAttributes(basicShape, jpt);
GraphicsUpdater.updateEntityShape(entityShape);
}
private ContainerShape createCompartmentRectangle(
ContainerShape entityShape, int y, String attribTxt) {
int width = entityShape.getGraphicsAlgorithm().getWidth();
ContainerShape containerShape = Graphiti.getPeService().createContainerShape(
entityShape, false);
Graphiti.getPeService().setPropertyValue(containerShape,
JPAEditorConstants.PROP_SHAPE_TYPE, ShapeType.COMPARTMENT
.toString());
Rectangle rect = addCompartmentRectangle(y, width, containerShape);
addCompartmentHeaderText(attribTxt, width, rect);
UpdateAttributeFeature updateFeature = new UpdateAttributeFeature(getFeatureProvider());
updateFeature.addSeparatorsToShape(containerShape);
return containerShape;
}
private Rectangle addCompartmentRectangle(int y, int width,
ContainerShape containerShape) {
Rectangle rect = Graphiti.getGaService().createRectangle(containerShape);
rect.setFilled(false);
rect.setLineVisible(false);
rect.setHeight(0);
rect.setWidth(width);
rect.setX(0);
rect.setY(y);
containerShape.setActive(true);
return rect;
}
private void addCompartmentHeaderText(String attribTxt, int width,
Rectangle rect) {
IJPAEditorFeatureProvider fp = getFeatureProvider();
Text text = UpdateAttributeFeature.addText(fp, rect, attribTxt);
text.getFont().setSize(7);
text.getFont().setItalic(true);
text.getFont().setBold(false);
Graphiti.getGaService().setWidth(text, width);
Graphiti.getGaService().setLocationAndSize(text, 0, 2, width,
13);
text.setHorizontalAlignment(Orientation.ALIGNMENT_CENTER);
text.setVerticalAlignment(Orientation.ALIGNMENT_CENTER);
}
private void addCompartmentChildren(
ContainerShape containerShape, JavaPersistentType jpt,
String attributeAnnotations) {
List<JavaPersistentAttribute> attributes = new ArrayList<JavaPersistentAttribute>();
for (JavaPersistentAttribute attribute : jpt.getAttributes()) {
HashSet<String> annotations = JpaArtifactFactory.instance().getAnnotationNames(attribute);
if (annotations.contains(attributeAnnotations)) {
attributes.add(attribute);
}
}
addAttributes(containerShape, attributes);
}
private void addBasicAttributes(ContainerShape containerShape, JavaPersistentType jpt){
List<JavaPersistentAttribute> attributes = new ArrayList<JavaPersistentAttribute>();
for (JavaPersistentAttribute attribute : jpt.getAttributes()){
HashSet<String> annotations = JpaArtifactFactory.instance().getAnnotationNames(attribute);
if(!(annotations.contains(JPAEditorConstants.ANNOTATION_ID))&& !(annotations.contains(JPAEditorConstants.ANNOTATION_EMBEDDED_ID)) && !(annotations.contains(JPAEditorConstants.ANNOTATION_MANY_TO_MANY)) &&
!(annotations.contains(JPAEditorConstants.ANNOTATION_MANY_TO_ONE)) && !(annotations.contains(JPAEditorConstants.ANNOTATION_ONE_TO_MANY))&&
!(annotations.contains(JPAEditorConstants.ANNOTATION_ONE_TO_ONE)) || annotations.isEmpty()){
attributes.add(attribute);
}
}
addAttributes(containerShape, attributes);
}
private void addAttributes(ContainerShape entityShape,
List<JavaPersistentAttribute> attributes) {
for (int i = 0; i < attributes.size(); i++) {
JavaPersistentAttribute jpa = attributes.get(i);
addAttribute(jpa, entityShape);
}
}
public interface IPeUtilFacade {
public ContainerShape createContainerShape(Diagram diagram, boolean b);
}
public static RoundedRectangle createEntityRectangle(IAddContext context,
ContainerShape entityShape, Diagram diagram) {
RoundedRectangle entityRectangle = Graphiti.getGaService().createRoundedRectangle(
entityShape, JPAEditorConstants.ENTITY_CORNER_WIDTH,
JPAEditorConstants.ENTITY_CORNER_HEIGHT);
entityRectangle
.setForeground(Graphiti.getGaService().manageColor(diagram, JPAEditorConstants.ENTITY_BORDER_COLOR));
entityRectangle
.setBackground(Graphiti.getGaService().manageColor(diagram, JPAEditorConstants.ENTITY_BACKGROUND));
Graphiti.getGaService().setRenderingStyle(entityRectangle.getPictogramElement().getGraphicsAlgorithm(),
PredefinedColoredAreas.getAdaptedGradientColoredAreas(IPredefinedRenderingStyle.BLUE_WHITE_GLOSS_ID));
entityRectangle.setLineWidth(JPAEditorConstants.ENTITY_BORDER_WIDTH);
entityRectangle.setLineStyle(LineStyle.SOLID);
Graphiti.getGaService().setLocationAndSize(entityRectangle, context
.getX(), context.getY(),
(context.getWidth() == -1) ? JPAEditorConstants.ENTITY_WIDTH
: context.getWidth(),
(context.getHeight() == -1) ? JPAEditorConstants.ENTITY_HEIGHT
: context.getHeight());
return entityRectangle;
}
private static class PeUtilFacade implements IPeUtilFacade {
public ContainerShape createContainerShape(Diagram diagram, boolean b) {
return Graphiti.getPeService().createContainerShape(diagram, true);
}
}
private ContainerShape addHeader(JavaPersistentType addedWrapper,
ContainerShape entityShape, int width) {
ContainerShape headerIconShape = Graphiti.getPeService().createContainerShape(
entityShape, false);
Rectangle iconRect = Graphiti.getGaService().createRectangle(headerIconShape);
iconRect.setFilled(false);
iconRect.setLineVisible(false);
iconRect.setHeight(JPAEditorConstants.ICON_RECT_HEIGHT);
iconRect.setX(0);
iconRect.setWidth(JPAEditorConstants.HEADER_ICON_RECT_WIDTH);
iconRect.setHeight(JPAEditorConstants.HEADER_ICON_RECT_HEIGHT);
iconRect.setY(0);
Image headerIcon = Graphiti.getGaService().createImage(iconRect,
JPAEditorImageProvider.JPA_ENTITY);
Graphiti.getGaService().setLocationAndSize(headerIcon,
JPAEditorConstants.ICON_HEADER_X,
JPAEditorConstants.ICON_HEADER_Y,
JPAEditorConstants.ICON_WIDTH,
JPAEditorConstants.ICON_HEIGHT);
Graphiti.getPeService().setPropertyValue(headerIconShape,
JPAEditorConstants.PROP_SHAPE_TYPE, ShapeType.ICON.toString());
ContainerShape entityHeaderTextShape = Graphiti.getPeService().createContainerShape(entityShape, false);
Graphiti.getPeService()
.setPropertyValue(entityHeaderTextShape,
JPAEditorConstants.PROP_SHAPE_TYPE, ShapeType.HEADER
.toString());
Rectangle headerRect = Graphiti.getGaService().createRectangle(entityHeaderTextShape);
headerRect.setFilled(false);
headerRect.setLineVisible(false);
headerRect.setWidth(width - JPAEditorConstants.HEADER_TEXT_RECT_WIDTH_REDUCER);
headerRect.setHeight(JPAEditorConstants.HEADER_TEXT_RECT_HEIGHT);
headerRect.setY(2);
headerRect.setX(JPAEditorConstants.HEADER_TEXT_RECT_X);
String headerTextString = JPAEditorUtil.getText(addedWrapper);
ICompilationUnit cu = getFeatureProvider().getCompilationUnit(addedWrapper);
JPAEditorUtil.becomeWorkingCopy(cu);
headerTextString = JPAEditorUtil.returnSimpleName(headerTextString);
try {
if (cu.hasUnsavedChanges()) {
headerTextString = JPAEditorConstants.HEADER_PREFIX_DIRTY + headerTextString;
}
} catch (JavaModelException e) {
JPADiagramEditorPlugin.logError("Cannot check compilation unit for unsaved changes", e); //$NON-NLS-1$
}
Text headerTextObj = Graphiti.getGaService().createDefaultText(getDiagram(), headerRect,
headerTextString);
headerTextObj
.setForeground(manageColor(JPAEditorConstants.ENTITY_TEXT_FOREGROUND));
headerTextObj.setHorizontalAlignment(Orientation.ALIGNMENT_LEFT);
headerTextObj.setVerticalAlignment(Orientation.ALIGNMENT_TOP);
headerTextObj.getFont().setBold(true);
Graphiti.getGaService().setLocationAndSize(headerTextObj, 1, 2,
width, 20);
return entityHeaderTextShape;
}
@SuppressWarnings("deprecation")
private void addAttribute(JavaPersistentAttribute pa,
ContainerShape compartmentShape) {
IJPAEditorFeatureProvider fp = getFeatureProvider();
fp.putKeyToBusinessObject(fp.getKeyForBusinessObject(pa), pa);
JavaPersistentType jpt = (JavaPersistentType)pa.getParent();
String key = fp.getKeyForBusinessObject(jpt);
if (fp.getBusinessObjectForKey(key) == null)
fp.putKeyToBusinessObject(key, jpt);
UpdateAttributeFeature updateFeature = new UpdateAttributeFeature(fp);
updateFeature.addAttributes(compartmentShape.getContainer(), pa);
updateFeature = null;
}
}