blob: b6517dca2224b7331528478feb81d5d3ad6e3d6c [file] [log] [blame]
/*******************************************************************************
* 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();
}
}
}