| /******************************************************************************* |
| * Copyright (c) 2009, 2015 Oracle. 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: |
| * Oracle - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.jpt.jpa.core.internal.jpa1.context.java; |
| |
| import java.util.List; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jpt.common.core.resource.java.JavaResourceAttribute; |
| import org.eclipse.jpt.common.core.utility.TextRange; |
| import org.eclipse.jpt.jpa.core.context.NamedColumn; |
| import org.eclipse.jpt.jpa.core.context.OrderBy; |
| import org.eclipse.jpt.jpa.core.context.java.JavaAttributeMapping; |
| import org.eclipse.jpt.jpa.core.context.java.JavaSpecifiedPersistentAttribute; |
| import org.eclipse.jpt.jpa.core.internal.context.JpaValidator; |
| import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaContextModel; |
| import org.eclipse.jpt.jpa.core.internal.jpa2.context.OrderColumnValidator; |
| import org.eclipse.jpt.jpa.core.internal.jpa2.context.java.GenericJavaOrderColumn2_0; |
| import org.eclipse.jpt.jpa.core.internal.jpa2.resource.java.OrderColumnAnnotationDefinition2_0; |
| import org.eclipse.jpt.jpa.core.jpa2.context.SpecifiedOrderColumn2_0; |
| import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaOrderable2_0; |
| import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaSpecifiedOrderColumn2_0; |
| import org.eclipse.jpt.jpa.core.jpa2.resource.java.OrderColumnAnnotation2_0; |
| import org.eclipse.jpt.jpa.core.resource.java.JPA; |
| import org.eclipse.jpt.jpa.core.resource.java.OrderByAnnotation; |
| import org.eclipse.jpt.jpa.core.validation.JptJpaCoreValidationMessages; |
| import org.eclipse.jpt.jpa.db.Table; |
| import org.eclipse.wst.validation.internal.provisional.core.IMessage; |
| import org.eclipse.wst.validation.internal.provisional.core.IReporter; |
| |
| /** |
| * Java ordering |
| * <p> |
| * <strong>(JPA 2.0 only) NB:</strong> If both the "order by" and the "order |
| * column" annotations are present (which is prohibited by the JPA spec), |
| * order by is ignored (although the model is still there) |
| */ |
| public class GenericJavaOrderable |
| extends AbstractJavaContextModel<JavaAttributeMapping> |
| implements JavaOrderable2_0 { |
| |
| protected final JavaOrderable2_0.ParentAdapter parentAdapter; |
| |
| protected boolean noOrdering = false; |
| |
| protected boolean orderByOrdering = false; |
| // never null |
| protected OrderBy orderBy; |
| |
| protected boolean orderColumnOrdering = false; |
| // never null |
| protected JavaSpecifiedOrderColumn2_0 orderColumn; |
| // JPA 1.0 |
| protected OrderColumnAnnotation2_0 nullOrderColumnAnnotation; |
| |
| |
| /** |
| * JPA 1.0 |
| */ |
| public GenericJavaOrderable(JavaAttributeMapping parent) { |
| this(new JavaOrderable2_0.ParentAdapter.Null(parent)); |
| } |
| |
| /** |
| * JPA 2.0 |
| */ |
| public GenericJavaOrderable(JavaOrderable2_0.ParentAdapter parentAdapter) { |
| super(parentAdapter.getOrderableParent()); |
| |
| this.parentAdapter = parentAdapter; |
| |
| initNoOrdering(); |
| initOrderBy(); |
| initOrderColumn(); |
| } |
| |
| |
| // ********** synchronize/update ********** |
| |
| @Override |
| public void synchronizeWithResourceModel(IProgressMonitor monitor) { |
| super.synchronizeWithResourceModel(monitor); |
| syncNoOrdering(); |
| syncOrderBy(monitor); |
| syncOrderColumn(monitor); |
| } |
| |
| @Override |
| public void update(IProgressMonitor monitor) { |
| super.update(monitor); |
| this.updateOrderBy(monitor); |
| this.updateOrderColumn(monitor); |
| } |
| |
| |
| // ****** no ordering ***** |
| |
| public boolean isNoOrdering() { |
| return this.noOrdering; |
| } |
| |
| public void setNoOrdering() { |
| removeOrderColumnAnnotation(); |
| removeOrderByAnnotation(); |
| |
| setNoOrdering_(true); |
| this.orderBy.setKey(null); |
| setOrderByOrdering_(false); |
| setOrderColumnOrdering_(false); |
| } |
| |
| protected void setNoOrdering_(boolean noOrdering) { |
| boolean old = this.noOrdering; |
| this.noOrdering = noOrdering; |
| this.firePropertyChanged(NO_ORDERING_PROPERTY, old, noOrdering); |
| } |
| |
| protected void initNoOrdering() { |
| this.noOrdering = buildNoOrdering(); |
| } |
| |
| protected void syncNoOrdering() { |
| setNoOrdering_(buildNoOrdering()); |
| } |
| |
| protected boolean buildNoOrdering() { |
| return isJpa2_0Compatible() ? buildNoOrdering2_0() : buildNoOrdering1_0(); |
| } |
| |
| /** |
| * both annotations are missing |
| */ |
| protected boolean buildNoOrdering2_0() { |
| return getOrderByAnnotation() == null && getOrderColumnAnnotation() == null; |
| } |
| |
| /** |
| * the order-by annotation is missing |
| */ |
| protected boolean buildNoOrdering1_0() { |
| return getOrderByAnnotation() == null; |
| } |
| |
| |
| // ***** order-by ordering ***** |
| |
| public boolean isOrderByOrdering() { |
| return this.orderByOrdering; |
| } |
| |
| public void setOrderByOrdering() { |
| removeOrderColumnAnnotation(); |
| if (getOrderByAnnotation() == null) { |
| addOrderByAnnotation(); |
| } |
| |
| setNoOrdering_(false); |
| setOrderByOrdering_(true); |
| setOrderColumnOrdering_(false); |
| } |
| |
| protected void setOrderByOrdering_(boolean orderByOrdering) { |
| boolean old = this.orderByOrdering; |
| this.orderByOrdering = orderByOrdering; |
| firePropertyChanged(ORDER_BY_ORDERING_PROPERTY, old, orderByOrdering); |
| } |
| |
| public OrderBy getOrderBy() { |
| return this.orderBy; |
| } |
| |
| protected void initOrderBy() { |
| this.orderByOrdering = buildOrderByOrdering(); |
| this.orderBy = buildOrderBy(); |
| } |
| |
| protected void syncOrderBy(IProgressMonitor monitor) { |
| setOrderByOrdering_(buildOrderByOrdering()); |
| this.orderBy.synchronizeWithResourceModel(monitor); |
| } |
| |
| protected void updateOrderBy(IProgressMonitor monitor) { |
| this.orderBy.update(monitor); |
| } |
| |
| protected boolean buildOrderByOrdering() { |
| return isJpa2_0Compatible() ? buildOrderByOrdering2_0() : buildOrderByOrdering1_0(); |
| } |
| |
| /** |
| * OrderBy annotation is present, but OrderColumn is absent |
| */ |
| protected boolean buildOrderByOrdering2_0() { |
| return getOrderByAnnotation() != null && getOrderColumnAnnotation() == null; |
| } |
| |
| /** |
| * OrderBy annotation is present |
| */ |
| protected boolean buildOrderByOrdering1_0() { |
| return getOrderByAnnotation() != null; |
| } |
| |
| protected OrderBy buildOrderBy() { |
| return new GenericJavaOrderBy(this, new OrderByContext()); |
| } |
| |
| protected class OrderByContext |
| implements GenericJavaOrderBy.Context { |
| |
| public OrderByAnnotation getAnnotation(boolean addIfAbsent) { |
| OrderByAnnotation annotation = GenericJavaOrderable.this.getOrderByAnnotation(); |
| if (annotation == null && addIfAbsent) { |
| annotation = addOrderByAnnotation(); |
| } |
| return annotation; |
| } |
| } |
| |
| |
| // ***** order by annotation ***** |
| |
| protected OrderByAnnotation getOrderByAnnotation() { |
| return (OrderByAnnotation) this.getResourceAttribute().getAnnotation(JPA.ORDER_BY); |
| } |
| |
| protected OrderByAnnotation addOrderByAnnotation() { |
| return (OrderByAnnotation) this.getResourceAttribute().addAnnotation(JPA.ORDER_BY); |
| } |
| |
| protected void removeOrderByAnnotation() { |
| if (getResourceAttribute().getAnnotation(JPA.ORDER_BY) != null) { |
| getResourceAttribute().removeAnnotation(JPA.ORDER_BY); |
| } |
| } |
| |
| |
| // ***** order column ordering ***** |
| |
| public boolean isOrderColumnOrdering() { |
| return this.orderColumnOrdering; |
| } |
| |
| public void setOrderColumnOrdering() { |
| removeOrderByAnnotation(); |
| if (getOrderColumnAnnotation() == null) { |
| addOrderColumnAnnotation(); |
| } |
| |
| setNoOrdering_(false); |
| setOrderByOrdering_(false); |
| this.orderBy.setKey(null); |
| setOrderColumnOrdering_(true); |
| } |
| |
| protected void setOrderColumnOrdering_(boolean orderColumnOrdering) { |
| boolean old = this.orderColumnOrdering; |
| this.orderColumnOrdering = orderColumnOrdering; |
| this.firePropertyChanged(ORDER_COLUMN_ORDERING_PROPERTY, old, orderColumnOrdering); |
| } |
| |
| public JavaSpecifiedOrderColumn2_0 getOrderColumn() { |
| return this.orderColumn; |
| } |
| |
| protected void initOrderColumn() { |
| this.orderColumnOrdering = buildOrderColumnOrdering(); |
| this.orderColumn = buildOrderColumn(); |
| } |
| |
| protected void syncOrderColumn(IProgressMonitor monitor) { |
| setOrderColumnOrdering_(buildOrderColumnOrdering()); |
| this.orderColumn.synchronizeWithResourceModel(monitor); |
| } |
| |
| protected void updateOrderColumn(IProgressMonitor monitor) { |
| this.orderColumn.update(monitor); |
| } |
| |
| /** |
| * Only true if JPA 2.0 *and* annotation is present |
| */ |
| protected boolean buildOrderColumnOrdering() { |
| return isJpa2_0Compatible() ? getOrderColumnAnnotation() != null : false; |
| } |
| |
| protected JavaSpecifiedOrderColumn2_0 buildOrderColumn() { |
| JavaSpecifiedOrderColumn2_0.ParentAdapter columnParentAdapter = new OrderColumnParentAdapter(); |
| return isJpa2_0Compatible() ? |
| getJpaFactory2_0().buildJavaOrderColumn(columnParentAdapter) : |
| new GenericJavaOrderColumn2_0(columnParentAdapter); |
| } |
| |
| |
| // ***** order column annotation ***** |
| |
| protected OrderColumnAnnotation2_0 getOrderColumnAnnotation() { |
| return (OrderColumnAnnotation2_0) this.getResourceAttribute().getAnnotation(OrderColumnAnnotation2_0.ANNOTATION_NAME); |
| } |
| |
| protected OrderColumnAnnotation2_0 addOrderColumnAnnotation() { |
| return (OrderColumnAnnotation2_0) this.getResourceAttribute().addAnnotation(OrderColumnAnnotation2_0.ANNOTATION_NAME); |
| } |
| |
| protected void removeOrderColumnAnnotation() { |
| if (getResourceAttribute().getAnnotation(OrderColumnAnnotation2_0.ANNOTATION_NAME) != null) { |
| getResourceAttribute().removeAnnotation(OrderColumnAnnotation2_0.ANNOTATION_NAME); |
| } |
| } |
| |
| /** |
| * If we are in a JPA 1.0 project, return a <em>null</em> annotation. |
| */ |
| public OrderColumnAnnotation2_0 getNonNullOrderColumnAnnotation() { |
| // hmmmm... |
| return this.isJpa2_0Compatible() ? |
| (OrderColumnAnnotation2_0) this.getResourceAttribute().getNonNullAnnotation(OrderColumnAnnotation2_0.ANNOTATION_NAME) : |
| this.getNullOrderColumnAnnotation(); |
| } |
| |
| protected OrderColumnAnnotation2_0 getNullOrderColumnAnnotation() { |
| if (this.nullOrderColumnAnnotation == null) { |
| this.nullOrderColumnAnnotation = this.buildNullOrderColumnAnnotation(); |
| } |
| return this.nullOrderColumnAnnotation; |
| } |
| |
| protected OrderColumnAnnotation2_0 buildNullOrderColumnAnnotation() { |
| // hmmmm... |
| return (OrderColumnAnnotation2_0) OrderColumnAnnotationDefinition2_0.instance().buildNullAnnotation(this.getResourceAttribute()); |
| } |
| |
| |
| // ***** misc ***** |
| |
| protected JavaAttributeMapping getAttributeMapping() { |
| return this.parent; |
| } |
| |
| protected JavaSpecifiedPersistentAttribute getPersistentAttribute() { |
| return this.getAttributeMapping().getPersistentAttribute(); |
| } |
| |
| public JavaResourceAttribute getResourceAttribute() { |
| return this.getPersistentAttribute().getResourceAttribute(); |
| } |
| |
| // JPA 2.0 only |
| public String getDefaultTableName() { |
| return this.parentAdapter.getTableName(); |
| } |
| |
| // JPA 2.0 only |
| protected Table resolveDbTable(String tableName) { |
| return this.parentAdapter.resolveDbTable(tableName); |
| } |
| |
| |
| // ***** content assist ***** |
| |
| @Override |
| public Iterable<String> getCompletionProposals(int pos) { |
| Iterable<String> result = super.getCompletionProposals(pos); |
| if (result != null) { |
| return result; |
| } |
| |
| return this.orderColumn.getCompletionProposals(pos); |
| } |
| |
| |
| // ***** validation ***** |
| |
| public TextRange getValidationTextRange() { |
| TextRange textRange = this.getOrderByAnnotationTextRange(); |
| return (textRange != null) ? textRange : this.getAttributeMapping().getValidationTextRange(); |
| } |
| |
| protected TextRange getOrderByAnnotationTextRange() { |
| OrderByAnnotation orderByAnnotation = this.getOrderByAnnotation(); |
| return (orderByAnnotation == null) ? null : orderByAnnotation.getTextRange(); |
| } |
| |
| @Override |
| public void validate(List<IMessage> messages, IReporter reporter) { |
| super.validate(messages, reporter); |
| if ((getOrderColumnAnnotation() != null) && (getOrderByAnnotation() != null)) { |
| if (this.getPersistentAttribute().isVirtual()) { |
| messages.add( |
| this.buildValidationMessage( |
| this.getAttributeMapping(), |
| this.getPersistentAttribute().getValidationTextRange(), |
| JptJpaCoreValidationMessages.ORDER_COLUMN_AND_ORDER_BY_BOTH_SPECIFIED, |
| this.getPersistentAttribute().getName() |
| ) |
| ); |
| } |
| else { |
| messages.add( |
| this.buildValidationMessage( |
| this.getAttributeMapping(), |
| this.getOrderByAnnotationTextRange(), |
| JptJpaCoreValidationMessages.ORDER_COLUMN_AND_ORDER_BY_BOTH_SPECIFIED, |
| this.getPersistentAttribute().getName() |
| ) |
| ); |
| } |
| } |
| if (this.orderColumnOrdering) { |
| //TODO validation message if type is not List |
| this.orderColumn.validate(messages, reporter); |
| } |
| } |
| |
| |
| // ***** order column parent adapter (JPA 2.0) ***** |
| |
| public class OrderColumnParentAdapter |
| implements JavaSpecifiedOrderColumn2_0.ParentAdapter { |
| |
| public JavaOrderable2_0 getColumnParent() { |
| return GenericJavaOrderable.this; |
| } |
| |
| public String getDefaultTableName() { |
| return GenericJavaOrderable.this.getDefaultTableName(); |
| } |
| |
| public Table resolveDbTable(String tableName) { |
| return GenericJavaOrderable.this.resolveDbTable(tableName); |
| } |
| |
| public String getDefaultColumnName(NamedColumn column) { |
| return this.getPersistentAttribute().getName() + "_ORDER"; //$NON-NLS-1$ |
| } |
| |
| public TextRange getValidationTextRange() { |
| return GenericJavaOrderable.this.getValidationTextRange(); |
| } |
| |
| public JpaValidator buildColumnValidator(NamedColumn column) { |
| return new OrderColumnValidator(this.getPersistentAttribute(), (SpecifiedOrderColumn2_0) column); |
| } |
| |
| public OrderColumnAnnotation2_0 getColumnAnnotation() { |
| return GenericJavaOrderable.this.getNonNullOrderColumnAnnotation(); |
| } |
| |
| public void removeColumnAnnotation() { |
| GenericJavaOrderable.this.removeOrderColumnAnnotation(); |
| } |
| |
| protected JavaSpecifiedPersistentAttribute getPersistentAttribute() { |
| return GenericJavaOrderable.this.getPersistentAttribute(); |
| } |
| } |
| } |