blob: bced5104169394390a01566f43b3520abed8aa79 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2011 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.jpa2.context.orm;
import java.util.List;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.utility.internal.ArrayTools;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.NotNullFilter;
import org.eclipse.jpt.common.utility.internal.Tools;
import org.eclipse.jpt.common.utility.internal.iterables.ArrayIterable;
import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable;
import org.eclipse.jpt.common.utility.internal.iterables.FilteringIterable;
import org.eclipse.jpt.common.utility.internal.iterables.SingleElementIterable;
import org.eclipse.jpt.common.utility.internal.iterables.TransformationIterable;
import org.eclipse.jpt.jpa.core.MappingKeys;
import org.eclipse.jpt.jpa.core.context.AttributeMapping;
import org.eclipse.jpt.jpa.core.context.Embeddable;
import org.eclipse.jpt.jpa.core.context.EmbeddedIdMapping;
import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentAttribute;
import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmXmlContextNode;
import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationDescriptionMessages;
import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmDerivedIdentity2_0;
import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmMapsIdDerivedIdentityStrategy2_0;
import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmSingleRelationshipMapping2_0;
import org.eclipse.jpt.jpa.core.resource.orm.v2_0.XmlSingleRelationshipMapping_2_0;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
public class GenericOrmMapsIdDerivedIdentityStrategy2_0
extends AbstractOrmXmlContextNode
implements OrmMapsIdDerivedIdentityStrategy2_0
{
protected String specifiedIdAttributeName;
// no default
public GenericOrmMapsIdDerivedIdentityStrategy2_0(OrmDerivedIdentity2_0 parent) {
super(parent);
this.specifiedIdAttributeName = this.getXmlMapping().getMapsId();
}
// ********** synchronize/update **********
@Override
public void synchronizeWithResourceModel() {
super.synchronizeWithResourceModel();
this.setSpecifiedIdAttributeName_(this.getXmlMapping().getMapsId());
}
// ********** ID attribute name **********
public String getIdAttributeName() {
// there is no default
return this.specifiedIdAttributeName;
}
public String getSpecifiedIdAttributeName() {
return this.specifiedIdAttributeName;
}
public void setSpecifiedIdAttributeName(String idAttributeName) {
this.setSpecifiedIdAttributeName_(idAttributeName);
this.getXmlMapping().setMapsId(idAttributeName);
}
protected void setSpecifiedIdAttributeName_(String idAttributeName) {
String old = this.specifiedIdAttributeName;
this.specifiedIdAttributeName = idAttributeName;
this.firePropertyChanged(SPECIFIED_ID_ATTRIBUTE_NAME_PROPERTY, old, idAttributeName);
}
public String getDefaultIdAttributeName() {
// there is no way to have a default in xml
return null;
}
public boolean defaultIdAttributeNameIsPossible() {
return false;
}
// ********** misc **********
@Override
public OrmDerivedIdentity2_0 getParent() {
return (OrmDerivedIdentity2_0) super.getParent();
}
protected OrmDerivedIdentity2_0 getDerivedIdentity() {
return this.getParent();
}
public OrmSingleRelationshipMapping2_0 getMapping() {
return this.getDerivedIdentity().getMapping();
}
protected OrmPersistentAttribute getPersistentAttribute() {
return this.getMapping().getPersistentAttribute();
}
protected XmlSingleRelationshipMapping_2_0 getXmlMapping() {
return this.getMapping().getXmlAttributeMapping();
}
protected Iterable<AttributeMapping> getAllAttributeMappings() {
return this.getPersistentAttribute().getOwningTypeMapping().getAllAttributeMappings();
}
public Iterable<String> getSortedCandidateIdAttributeNames() {
return CollectionTools.sort(this.getNonNullCandidateIdAttributeNames());
}
protected Iterable<String> getNonNullCandidateIdAttributeNames() {
return new FilteringIterable<String>(this.getCandidateIdAttributeNames(), NotNullFilter.<String>instance());
}
protected Iterable<String> getCandidateIdAttributeNames() {
return new TransformationIterable<AttributeMapping, String>(this.getCandidateIdAttributeMappings()) {
@Override
protected String transform(AttributeMapping mapping) {
return mapping.getName();
}
};
}
protected Iterable<AttributeMapping> getCandidateIdAttributeMappings() {
return this.buildCandidateIdAttributeMappings(this.getAllAttributeMappings());
}
protected Iterable<AttributeMapping> buildCandidateIdAttributeMappings(Iterable<AttributeMapping> attributeMappings) {
return new CompositeIterable<AttributeMapping>(this.getCandidateIdAttributeMappingLists(attributeMappings));
}
protected Iterable<Iterable<AttributeMapping>> getCandidateIdAttributeMappingLists(Iterable<AttributeMapping> attributeMappings) {
return new TransformationIterable<AttributeMapping, Iterable<AttributeMapping>>(attributeMappings) {
@Override
protected Iterable<AttributeMapping> transform(AttributeMapping attributeMapping) {
return Tools.valuesAreEqual(attributeMapping.getKey(), MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY) ?
this.getEmbeddedIdMappingChoiceIterable((EmbeddedIdMapping) attributeMapping) :
new SingleElementIterable<AttributeMapping>(attributeMapping);
}
/**
* Convert the specified mapping into a collection of its "mappings".
* Typically, this collection will include just the mapping itself;
* but, if the mapping is an embedded ID, this collection will include
* the mapping itself plus all the mappings of its target embeddable.
*
* NB: Recursion is unnecessary.
*/
protected Iterable<AttributeMapping> getEmbeddedIdMappingChoiceIterable(EmbeddedIdMapping mapping) {
Embeddable embeddable = mapping.getTargetEmbeddable();
if (embeddable == null) {
return new SingleElementIterable<AttributeMapping>(mapping);
}
return new CompositeIterable<AttributeMapping>(
mapping,
embeddable.getAllAttributeMappings()
);
}
};
}
public AttributeMapping getDerivedIdAttributeMapping() {
String idAttributeName = this.getIdAttributeName();
if (idAttributeName != null) {
for (AttributeMapping mapping : this.getCandidateIdAttributeMappings()) {
if (idAttributeName.equals(mapping.getName())) {
return mapping;
}
}
}
return null;
}
public boolean isSpecified() {
return this.getXmlMapping().getMapsId() != null;
}
public void addStrategy() {
this.getXmlMapping().setMapsId(""); //$NON-NLS-1$
}
public void removeStrategy() {
this.getXmlMapping().setMapsId(null);
}
public void initializeFrom(OrmMapsIdDerivedIdentityStrategy2_0 oldStrategy) {
this.setSpecifiedIdAttributeName(oldStrategy.getSpecifiedIdAttributeName());
}
// ********** ID mappings **********
protected Iterable<AttributeMapping> getIdAttributeMappings() {
return new FilteringIterable<AttributeMapping>(this.getAllAttributeMappings()) {
@Override
protected boolean accept(AttributeMapping mapping) {
return GenericOrmMapsIdDerivedIdentityStrategy2_0.this.mappingIsIdMapping(mapping);
}
};
}
protected boolean mappingIsIdMapping(AttributeMapping mapping) {
return CollectionTools.contains(this.getIdMappingKeys(), mapping.getKey());
}
protected Iterable<String> getIdMappingKeys() {
return ID_MAPPING_KEYS;
}
protected static final String[] ID_MAPPING_KEYS_ARRAY = new String[] {
MappingKeys.ID_ATTRIBUTE_MAPPING_KEY,
MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY
};
protected static final Iterable<String> ID_MAPPING_KEYS = new ArrayIterable<String>(ID_MAPPING_KEYS_ARRAY);
// ********** validation **********
@Override
public void validate(List<IMessage> messages, IReporter reporter) {
super.validate(messages, reporter);
this.validateMapsId(messages);
}
protected void validateMapsId(List<IMessage> messages) {
if (this.getDerivedIdentity().usesMapsIdDerivedIdentityStrategy()) {
this.validateMapsId_(messages);
}
}
protected void validateMapsId_(List<IMessage> messages) {
// test whether id attribute name can be resolved
AttributeMapping attributeMapping = this.getDerivedIdAttributeMapping();
if (attributeMapping == null) {
// there is no defaulting, so only use the 'resolved' error, even if the name is an empty string
messages.add(this.buildMessage(JpaValidationMessages.MAPS_ID_VALUE_NOT_RESOLVED, new String[] {this.getIdAttributeName()}));
} else {
// test whether attribute mapping is allowable
if ( ! CollectionTools.contains(this.getValidAttributeMappingChoices(), attributeMapping)) {
messages.add(this.buildMessage(JpaValidationMessages.MAPS_ID_VALUE_INVALID, new String[] {this.getIdAttributeName()}));
}
}
}
protected Iterable<AttributeMapping> getValidAttributeMappingChoices() {
return this.buildCandidateIdAttributeMappings(this.getIdAttributeMappings());
}
protected IMessage buildMessage(String msgID, String[] parms) {
String attributeDescription = NLS.bind(JpaValidationDescriptionMessages.ATTRIBUTE_DESC, this.getPersistentAttribute().getName());
parms = ArrayTools.add(parms, 0, attributeDescription);
return DefaultJpaValidationMessages.buildMessage(
IMessage.HIGH_SEVERITY,
msgID,
parms,
this,
this.getValidationTextRange()
);
}
public TextRange getValidationTextRange() {
TextRange textRange = this.getXmlMapping().getMapsIdTextRange();
return (textRange != null) ? textRange : this.getDerivedIdentity().getValidationTextRange();
}
}