blob: ed1f5d7a571ec4947e74ce4deb640b99b5632bd4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2008 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.core.internal.context.java;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jpt.core.internal.context.base.FetchType;
import org.eclipse.jpt.core.internal.context.base.IEntity;
import org.eclipse.jpt.core.internal.context.base.IMultiRelationshipMapping;
import org.eclipse.jpt.core.internal.context.base.INonOwningMapping;
import org.eclipse.jpt.core.internal.context.base.IPersistentAttribute;
import org.eclipse.jpt.core.internal.resource.java.JavaPersistentAttributeResource;
import org.eclipse.jpt.core.internal.resource.java.MapKey;
import org.eclipse.jpt.core.internal.resource.java.OrderBy;
import org.eclipse.jpt.core.internal.resource.java.RelationshipMapping;
import org.eclipse.jpt.core.internal.validation.IJpaValidationMessages;
import org.eclipse.jpt.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.utility.internal.Filter;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
public abstract class JavaMultiRelationshipMapping<T extends RelationshipMapping>
extends JavaRelationshipMapping<T> implements IMultiRelationshipMapping
{
protected String mappedBy;
protected String orderBy;
protected final IJavaJoinTable joinTable;
protected String mapKey;
protected JavaMultiRelationshipMapping(IJavaPersistentAttribute parent) {
super(parent);
this.joinTable = jpaFactory().createJavaJoinTable(this);
}
// @Override
// protected void notifyChanged(Notification notification) {
// super.notifyChanged(notification);
// switch (notification.getFeatureID(INonOwningMapping.class)) {
// case JpaCoreMappingsPackage.INON_OWNING_MAPPING__MAPPED_BY :
// this.mappedByAdapter.setValue((String) notification.getNewValue());
// break;
// default :
// break;
// }
// switch (notification.getFeatureID(IMultiRelationshipMapping.class)) {
// case JpaCoreMappingsPackage.IMULTI_RELATIONSHIP_MAPPING__ORDER_BY :
// String orderBy = (String) notification.getNewValue();
// if (orderBy == null) {
// this.orderByAnnotationAdapter.removeAnnotation();
// }
// else if ("".equals(orderBy)) {
// Annotation orderByAnnotation = this.orderByAnnotationAdapter.getAnnotation();
// if (orderByAnnotation != null) {
// // if the value is already "", then leave it alone (short circuit java change cycle)
// if (!"".equals(orderByValueAdapter.getValue())) {
// this.orderByValueAdapter.setValue(null);
// }
// }
// else {
// this.orderByAnnotationAdapter.newMarkerAnnotation();
// }
// }
// else {
// this.orderByValueAdapter.setValue(orderBy);
// }
// break;
// case JpaCoreMappingsPackage.IMULTI_RELATIONSHIP_MAPPING__MAP_KEY :
// String mk = (String) notification.getNewValue();
// if (mk == null) {
// this.mapKeyAnnotationAdapter.removeAnnotation();
// }
// else {
// this.mapKeyNameAdapter.setValue(mk);
// }
// break;
// case JpaCoreMappingsPackage.IMULTI_RELATIONSHIP_MAPPING__FETCH :
// this.getFetchAdapter().setValue(((DefaultLazyFetchType) notification.getNewValue()).convertToJavaAnnotationValue());
// break;
// default :
// break;
// }
// }
public String getMappedBy() {
return this.mappedBy;
}
public void setMappedBy(String newMappedBy) {
String oldMappedBy = this.mappedBy;
this.mappedBy = newMappedBy;
this.setMappedByOnResourceModel(newMappedBy);
firePropertyChanged(INonOwningMapping.MAPPED_BY_PROPERTY, oldMappedBy, newMappedBy);
}
protected abstract void setMappedByOnResourceModel(String mappedBy);
public String getOrderBy() {
return this.orderBy;
}
public void setOrderBy(String newOrderBy) {
String oldOrderBy = this.orderBy;
this.orderBy = newOrderBy;
if (oldOrderBy != newOrderBy) {
if (this.orderByResource(this.persistentAttributeResource) != null) {
if (newOrderBy != null) {
this.orderByResource(this.persistentAttributeResource).setValue(newOrderBy);
}
else {
this.persistentAttributeResource.removeAnnotation(OrderBy.ANNOTATION_NAME);
}
}
else if (newOrderBy != null) {
this.persistentAttributeResource.addAnnotation(OrderBy.ANNOTATION_NAME);
orderByResource(this.persistentAttributeResource).setValue(newOrderBy);
}
}
firePropertyChanged(IMultiRelationshipMapping.ORDER_BY_PROPERTY, oldOrderBy, newOrderBy);
}
protected void setOrderBy_(String newOrderBy) {
String oldOrderBy = this.orderBy;
this.orderBy = newOrderBy;
firePropertyChanged(IMultiRelationshipMapping.ORDER_BY_PROPERTY, oldOrderBy, newOrderBy);
}
protected OrderBy orderByResource(JavaPersistentAttributeResource persistentAttributeResource) {
return (OrderBy) persistentAttributeResource.annotation(OrderBy.ANNOTATION_NAME);
}
public boolean isNoOrdering() {
return getOrderBy() == null;
}
public void setNoOrdering() {
setOrderBy(null);
}
public boolean isOrderByPk() {
return "".equals(getOrderBy());
}
public void setOrderByPk() {
setOrderBy("");
}
public boolean isCustomOrdering() {
return !StringTools.stringIsEmpty(getOrderBy());
}
public FetchType getDefaultFetch() {
return IMultiRelationshipMapping.DEFAULT_FETCH_TYPE;
}
public IJavaJoinTable getJoinTable() {
return this.joinTable;
}
public boolean isJoinTableSpecified() {
return getJoinTable().isSpecified();
}
public String getMapKey() {
return this.mapKey;
}
public void setMapKey(String newMapKey) {
String oldMapKey = this.mapKey;
this.mapKey = newMapKey;
if (oldMapKey != newMapKey) {
if (this.mapKeyResource(this.persistentAttributeResource) != null) {
if (newMapKey != null) {
this.mapKeyResource(this.persistentAttributeResource).setName(newMapKey);
}
else {
this.persistentAttributeResource.removeAnnotation(MapKey.ANNOTATION_NAME);
}
}
else if (newMapKey != null) {
this.persistentAttributeResource.addAnnotation(MapKey.ANNOTATION_NAME);
mapKeyResource(this.persistentAttributeResource).setName(newMapKey);
}
}
firePropertyChanged(IMultiRelationshipMapping.MAP_KEY_PROPERTY, oldMapKey, newMapKey);
}
protected void setMapKey_(String newMapKey) {
String oldMapKey = this.mapKey;
this.mapKey = newMapKey;
firePropertyChanged(IMultiRelationshipMapping.MAP_KEY_PROPERTY, oldMapKey, newMapKey);
}
//TODO default orderBy - this wasn't supported in 1.0 either
// public void refreshDefaults(DefaultsContext defaultsContext) {
// super.refreshDefaults(defaultsContext);
// // if (isOrderByPk()) {
// // refreshDefaultOrderBy(defaultsContext);
// // }
// }
//
// //primary key ordering when just the @OrderBy annotation is present
// protected void refreshDefaultOrderBy(DefaultsContext defaultsContext) {
// IEntity targetEntity = getResolvedTargetEntity();
// if (targetEntity != null) {
// setOrderBy(targetEntity.primaryKeyAttributeName() + " ASC");
// }
// }
// private void updateOrderByFromJava(CompilationUnit astRoot) {
// String orderBy = this.orderByValueAdapter.getValue(astRoot);
// if (orderBy == null) {
// if (orderByAnnotation(astRoot) == null) {
// this.setNoOrdering();
// }
// else {
// this.setOrderByPk();
// }
// }
// else if ("".equals(orderBy)) {
// this.setOrderByPk();
// }
// else {
// this.setOrderBy(orderBy);
// }
// }
//
// private Annotation orderByAnnotation(CompilationUnit astRoot) {
// return this.orderByAnnotationAdapter.getAnnotation(astRoot);
// }
//
// private void updateMapKeyFromJava(CompilationUnit astRoot) {
// this.setMapKey(this.mapKeyNameAdapter.getValue(astRoot));
// }
@Override
protected String defaultTargetEntity(JavaPersistentAttributeResource persistentAttributeResource) {
if (!persistentAttributeResource.typeIsContainer()) {
return null;
}
return persistentAttributeResource.getQualifiedReferenceEntityElementTypeName();
}
protected abstract boolean mappedByTouches(int pos, CompilationUnit astRoot);
protected boolean mapKeyNameTouches(int pos, CompilationUnit astRoot) {
if (mapKeyResource(this.persistentAttributeResource) != null) {
return mapKeyResource(this.persistentAttributeResource).nameTouches(pos, astRoot);
}
return false;
}
protected MapKey mapKeyResource(JavaPersistentAttributeResource persistentAttributeResource) {
return (MapKey) persistentAttributeResource.annotation(MapKey.ANNOTATION_NAME);
}
public Iterator<String> candidateMapKeyNames() {
return this.allTargetEntityAttributeNames();
}
protected Iterator<String> candidateMapKeyNames(Filter<String> filter) {
return new FilteringIterator<String, String>(this.candidateMapKeyNames(), filter);
}
protected Iterator<String> quotedCandidateMapKeyNames(Filter<String> filter) {
return StringTools.quote(this.candidateMapKeyNames(filter));
}
@Override
public Iterator<String> candidateValuesFor(int pos, Filter<String> filter, CompilationUnit astRoot) {
Iterator<String> result = super.candidateValuesFor(pos, filter, astRoot);
if (result != null) {
return result;
}
result = this.getJoinTable().candidateValuesFor(pos, filter, astRoot);
if (result != null) {
return result;
}
if (this.mappedByTouches(pos, astRoot)) {
return this.quotedCandidateMappedByAttributeNames(filter);
}
if (this.mapKeyNameTouches(pos, astRoot)) {
return this.quotedCandidateMapKeyNames(filter);
}
return null;
}
@Override
public void initializeFromResource(JavaPersistentAttributeResource persistentAttributeResource) {
super.initializeFromResource(persistentAttributeResource);
MapKey mapKey = this.mapKeyResource(persistentAttributeResource);
if (mapKey != null) {
this.mapKey = mapKey.getName();
}
OrderBy orderBy = this.orderByResource(persistentAttributeResource);
if (orderBy != null) {
this.orderBy = orderBy.getValue();
}
this.joinTable.initializeFromResource(persistentAttributeResource);
}
@Override
protected void initialize(T relationshipMapping) {
super.initialize(relationshipMapping);
this.mappedBy = this.mappedBy(relationshipMapping);
}
@Override
public void update(JavaPersistentAttributeResource persistentAttributeResource) {
super.update(persistentAttributeResource);
this.updateMapKey(persistentAttributeResource);
this.updateOrderBy(persistentAttributeResource);
this.joinTable.update(persistentAttributeResource);
}
protected void updateMapKey(JavaPersistentAttributeResource persistentAttributeResource) {
MapKey mapKey = this.mapKeyResource(persistentAttributeResource);
if (mapKey != null) {
setMapKey_(mapKey.getName());
}
else {
setMapKey_(null);
}
}
protected void updateOrderBy(JavaPersistentAttributeResource persistentAttributeResource) {
OrderBy orderBy = this.orderByResource(persistentAttributeResource);
if (orderBy != null) {
setOrderBy_(orderBy.getValue());
}
else {
setOrderBy_(null);
}
}
@Override
protected void update(T relationshipMapping) {
super.update(relationshipMapping);
this.setMappedBy(this.mappedBy(relationshipMapping));
}
protected abstract String mappedBy(T relationshipMapping);
//******** Validation ***********************************
public void addToMessages(List<IMessage> messages, CompilationUnit astRoot) {
super.addToMessages(messages, astRoot);
if (this.isJoinTableSpecified()) {
addJoinTableMessages(messages, astRoot);
}
if (this.getMappedBy() != null) {
addMappedByMessages(messages, astRoot);
}
}
protected void addJoinTableMessages(List<IMessage> messages, CompilationUnit astRoot) {
IJavaJoinTable joinTable = this.getJoinTable();
boolean doContinue = joinTable.isConnected();
String schema = joinTable.getSchema();
if (doContinue && ! joinTable.hasResolvedSchema()) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.JOIN_TABLE_UNRESOLVED_SCHEMA,
new String[] {schema, joinTable.getName()},
joinTable, joinTable.schemaTextRange(astRoot))
);
doContinue = false;
}
if (doContinue && ! joinTable.isResolved()) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.JOIN_TABLE_UNRESOLVED_NAME,
new String[] {joinTable.getName()},
joinTable, joinTable.nameTextRange(astRoot))
);
doContinue = false;
}
for (Iterator<IJavaJoinColumn> stream = joinTable.joinColumns(); stream.hasNext(); ) {
IJavaJoinColumn joinColumn = stream.next();
if (doContinue && ! joinColumn.isResolved()) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.JOIN_COLUMN_UNRESOLVED_NAME,
new String[] {joinColumn.getName()},
joinColumn, joinColumn.nameTextRange(astRoot))
);
}
if (doContinue && ! joinColumn.isReferencedColumnResolved()) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME,
new String[] {joinColumn.getReferencedColumnName(), joinColumn.getName()},
joinColumn, joinColumn.referencedColumnNameTextRange(astRoot))
);
}
}
for (Iterator<IJavaJoinColumn> stream = joinTable.inverseJoinColumns(); stream.hasNext(); ) {
IJavaJoinColumn joinColumn = stream.next();
if (doContinue && ! joinColumn.isResolved()) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.JOIN_COLUMN_UNRESOLVED_NAME,
new String[] {joinColumn.getName()},
joinColumn, joinColumn.nameTextRange(astRoot))
);
}
if (doContinue && ! joinColumn.isReferencedColumnResolved()) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.JOIN_COLUMN_REFERENCED_COLUMN_UNRESOLVED_NAME,
new String[] {joinColumn.getReferencedColumnName(), joinColumn.getName()},
joinColumn, joinColumn.referencedColumnNameTextRange(astRoot))
);
}
}
}
protected void addMappedByMessages(List<IMessage> messages, CompilationUnit astRoot) {
String mappedBy = this.getMappedBy();
if (this.isJoinTableSpecified()) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.MAPPING_MAPPED_BY_WITH_JOIN_TABLE,
this.getJoinTable(), this.getJoinTable().validationTextRange(astRoot))
);
}
IEntity targetEntity = this.getResolvedTargetEntity();
if (targetEntity == null) {
// already have validation messages for that
return;
}
IPersistentAttribute attribute = targetEntity.persistentType().resolveAttribute(mappedBy);
if (attribute == null) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.MAPPING_UNRESOLVED_MAPPED_BY,
new String[] {mappedBy},
this, this.mappedByTextRange(astRoot))
);
return;
}
if (! this.mappedByIsValid(attribute.getMapping())) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.MAPPING_INVALID_MAPPED_BY,
new String[] {mappedBy},
this, this.mappedByTextRange(astRoot))
);
return;
}
INonOwningMapping mappedByMapping;
try {
mappedByMapping = (INonOwningMapping) attribute.getMapping();
} catch (ClassCastException cce) {
// there is no error then
return;
}
if (mappedByMapping.getMappedBy() != null) {
messages.add(
JpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
IJpaValidationMessages.MAPPING_MAPPED_BY_ON_BOTH_SIDES,
this, this.mappedByTextRange(astRoot))
);
}
}
}