blob: 027151e02d9a6ca5756a55522021391ccf5a5e7e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 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.jpa1.context.java;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jpt.core.context.BaseColumn;
import org.eclipse.jpt.core.context.BaseOverride;
import org.eclipse.jpt.core.context.Column;
import org.eclipse.jpt.core.context.NamedColumn;
import org.eclipse.jpt.core.context.TypeMapping;
import org.eclipse.jpt.core.context.java.JavaAttributeOverride;
import org.eclipse.jpt.core.context.java.JavaAttributeOverrideContainer;
import org.eclipse.jpt.core.context.java.JavaJpaContextNode;
import org.eclipse.jpt.core.internal.context.java.AbstractJavaJpaContextNode;
import org.eclipse.jpt.core.internal.context.java.VirtualAttributeOverrideAnnotation;
import org.eclipse.jpt.core.resource.java.Annotation;
import org.eclipse.jpt.core.resource.java.AttributeOverrideAnnotation;
import org.eclipse.jpt.core.resource.java.AttributeOverridesAnnotation;
import org.eclipse.jpt.core.resource.java.JavaResourcePersistentMember;
import org.eclipse.jpt.core.resource.java.NestableAnnotation;
import org.eclipse.jpt.core.utility.TextRange;
import org.eclipse.jpt.db.Table;
import org.eclipse.jpt.utility.Filter;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.iterators.CloneListIterator;
import org.eclipse.jpt.utility.internal.iterators.CompositeListIterator;
import org.eclipse.jpt.utility.internal.iterators.FilteringIterator;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
public class GenericJavaAttributeOverrideContainer extends AbstractJavaJpaContextNode
implements JavaAttributeOverrideContainer
{
protected JavaResourcePersistentMember javaResourcePersistentMember;
protected final List<JavaAttributeOverride> specifiedAttributeOverrides;
protected final List<JavaAttributeOverride> virtualAttributeOverrides;
protected final Owner owner;
public GenericJavaAttributeOverrideContainer(JavaJpaContextNode parent, Owner owner) {
super(parent);
this.owner = owner;
this.specifiedAttributeOverrides = new ArrayList<JavaAttributeOverride>();
this.virtualAttributeOverrides = new ArrayList<JavaAttributeOverride>();
}
protected Owner getOwner() {
return this.owner;
}
@SuppressWarnings("unchecked")
public ListIterator<JavaAttributeOverride> attributeOverrides() {
return new CompositeListIterator<JavaAttributeOverride>(specifiedAttributeOverrides(), virtualAttributeOverrides());
}
public int attributeOverridesSize() {
return this.specifiedAttributeOverridesSize() + this.virtualAttributeOverridesSize();
}
public ListIterator<JavaAttributeOverride> virtualAttributeOverrides() {
return new CloneListIterator<JavaAttributeOverride>(this.virtualAttributeOverrides);
}
public int virtualAttributeOverridesSize() {
return this.virtualAttributeOverrides.size();
}
public ListIterator<JavaAttributeOverride> specifiedAttributeOverrides() {
return new CloneListIterator<JavaAttributeOverride>(this.specifiedAttributeOverrides);
}
public int specifiedAttributeOverridesSize() {
return this.specifiedAttributeOverrides.size();
}
protected JavaAttributeOverride addSpecifiedAttributeOverride(int index) {
JavaAttributeOverride attributeOverride = getJpaFactory().buildJavaAttributeOverride(this, createAttributeOverrideOwner());
this.specifiedAttributeOverrides.add(index, attributeOverride);
AttributeOverrideAnnotation attributeOverrideResource =
(AttributeOverrideAnnotation) this.javaResourcePersistentMember.addAnnotation(
index, AttributeOverrideAnnotation.ANNOTATION_NAME,
AttributeOverridesAnnotation.ANNOTATION_NAME);
attributeOverride.initialize(attributeOverrideResource);
this.fireItemAdded(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, index, attributeOverride);
return attributeOverride;
}
protected JavaAttributeOverride setAttributeOverrideVirtual(boolean virtual, JavaAttributeOverride attributeOverride) {
// Add a new attribute override
if (virtual) {
return setAttributeOverrideVirtual(attributeOverride);
}
return setAttributeOverrideSpecified(attributeOverride);
}
protected JavaAttributeOverride setAttributeOverrideVirtual(JavaAttributeOverride specifiedAttributeOverride) {
int index = this.specifiedAttributeOverrides.indexOf(specifiedAttributeOverride);
this.specifiedAttributeOverrides.remove(index);
String attributeOverrideName = specifiedAttributeOverride.getName();
//add the virtual attribute override so that I can control the order that change notification is sent.
//otherwise when we remove the annotation from java we will get an update and add the attribute override
//during the update. This causes the UI to be flaky, since change notification might not occur in the correct order
JavaAttributeOverride virtualAttributeOverride = null;
if (attributeOverrideName != null) {
for (String name : CollectionTools.iterable(allOverridableAttributeNames())) {
if (name.equals(attributeOverrideName)) {
//store the virtualAttributeOverride so we can fire change notification later
virtualAttributeOverride = buildVirtualAttributeOverride(name);
this.virtualAttributeOverrides.add(virtualAttributeOverride);
break;
}
}
}
this.javaResourcePersistentMember.removeAnnotation(
this.resourceIndexOf(specifiedAttributeOverride),
AttributeOverrideAnnotation.ANNOTATION_NAME,
AttributeOverridesAnnotation.ANNOTATION_NAME);
fireItemRemoved(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, index, specifiedAttributeOverride);
if (virtualAttributeOverride != null) {
fireItemAdded(VIRTUAL_ATTRIBUTE_OVERRIDES_LIST, virtualAttributeOverridesSize() - 1, virtualAttributeOverride);
}
return virtualAttributeOverride;
}
protected JavaAttributeOverride setAttributeOverrideSpecified(JavaAttributeOverride virtualAttributeOverride) {
int index = specifiedAttributeOverridesSize();
int resourceIndex = 0;
if (specifiedAttributeOverridesSize() > 0) {
resourceIndex = this.resourceIndexOf(this.specifiedAttributeOverrides.get(index - 1)) + 1;
}
JavaAttributeOverride specifiedAttributeOverride = getJpaFactory().buildJavaAttributeOverride(this, createAttributeOverrideOwner());
AttributeOverrideAnnotation attributeOverrideResource =
(AttributeOverrideAnnotation) this.javaResourcePersistentMember.addAnnotation(
resourceIndex,
AttributeOverrideAnnotation.ANNOTATION_NAME,
AttributeOverridesAnnotation.ANNOTATION_NAME);
specifiedAttributeOverride.initialize(attributeOverrideResource);
int defaultIndex = this.virtualAttributeOverrides.indexOf(virtualAttributeOverride);
this.virtualAttributeOverrides.remove(defaultIndex);
String name = virtualAttributeOverride.getName();
String prefix = getOwner().getWritePrefix();
if (prefix != null) {
name = prefix + name;
}
this.specifiedAttributeOverrides.add(index, specifiedAttributeOverride);
specifiedAttributeOverride.setName(name);
specifiedAttributeOverride.getColumn().setSpecifiedName(virtualAttributeOverride.getColumn().getName());
this.fireItemRemoved(VIRTUAL_ATTRIBUTE_OVERRIDES_LIST, defaultIndex, virtualAttributeOverride);
this.fireItemAdded(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, index, specifiedAttributeOverride);
return specifiedAttributeOverride;
}
protected JavaAttributeOverride.Owner createAttributeOverrideOwner() {
return new AttributeOverrideOwner();
}
protected void addSpecifiedAttributeOverride(int index, JavaAttributeOverride attributeOverride) {
addItemToList(index, attributeOverride, this.specifiedAttributeOverrides, SPECIFIED_ATTRIBUTE_OVERRIDES_LIST);
}
protected void addSpecifiedAttributeOverride(JavaAttributeOverride attributeOverride) {
this.addSpecifiedAttributeOverride(this.specifiedAttributeOverrides.size(), attributeOverride);
}
protected void removeSpecifiedAttributeOverride_(JavaAttributeOverride attributeOverride) {
removeItemFromList(attributeOverride, this.specifiedAttributeOverrides, SPECIFIED_ATTRIBUTE_OVERRIDES_LIST);
}
public void moveSpecifiedAttributeOverride(int targetIndex, int sourceIndex) {
CollectionTools.move(this.specifiedAttributeOverrides, targetIndex, sourceIndex);
this.javaResourcePersistentMember.moveAnnotation(
targetIndex, sourceIndex, AttributeOverridesAnnotation.ANNOTATION_NAME);
fireItemMoved(SPECIFIED_ATTRIBUTE_OVERRIDES_LIST, targetIndex, sourceIndex);
}
protected void addVirtualAttributeOverride(JavaAttributeOverride attributeOverride) {
addItemToList(attributeOverride, this.virtualAttributeOverrides, VIRTUAL_ATTRIBUTE_OVERRIDES_LIST);
}
protected void removeVirtualAttributeOverride(JavaAttributeOverride attributeOverride) {
removeItemFromList(attributeOverride, this.virtualAttributeOverrides, VIRTUAL_ATTRIBUTE_OVERRIDES_LIST);
}
public JavaAttributeOverride getAttributeOverrideNamed(String name) {
return (JavaAttributeOverride) getOverrideNamed(name, attributeOverrides());
}
public boolean containsAttributeOverride(String name) {
return containsOverride(name, attributeOverrides());
}
public boolean containsDefaultAttributeOverride(String name) {
return containsOverride(name, virtualAttributeOverrides());
}
public boolean containsSpecifiedAttributeOverride(String name) {
return containsOverride(name, specifiedAttributeOverrides());
}
protected BaseOverride getOverrideNamed(String name, ListIterator<? extends BaseOverride> overrides) {
for (BaseOverride override : CollectionTools.iterable(overrides)) {
String overrideName = override.getName();
if (overrideName == null && name == null) {
return override;
}
if (overrideName != null && overrideName.equals(name)) {
return override;
}
}
return null;
}
protected boolean containsOverride(String name, ListIterator<? extends BaseOverride> overrides) {
return getOverrideNamed(name, overrides) != null;
}
protected Iterator<String> allOverridableAttributeNames() {
return getOwner().allOverridableNames();
}
public void initialize(JavaResourcePersistentMember resourcePersistentMember) {
this.javaResourcePersistentMember = resourcePersistentMember;
this.initializeSpecifiedAttributeOverrides();
this.initializeVirtualAttributeOverrides();
}
protected void initializeSpecifiedAttributeOverrides() {
for (Iterator<NestableAnnotation> stream = this.relavantResourceAttributeOverrides(); stream.hasNext(); ) {
this.specifiedAttributeOverrides.add(
buildAttributeOverride((AttributeOverrideAnnotation) stream.next()));
}
}
protected void initializeVirtualAttributeOverrides() {
for (String name : CollectionTools.iterable(allOverridableAttributeNames())) {
JavaAttributeOverride attributeOverride = getAttributeOverrideNamed(name);
if (attributeOverride == null) {
this.virtualAttributeOverrides.add(buildVirtualAttributeOverride(name));
}
}
}
public void update(JavaResourcePersistentMember resourcePersistentMember) {
this.javaResourcePersistentMember = resourcePersistentMember;
this.updateSpecifiedAttributeOverrides();
this.updateVirtualAttributeOverrides();
}
protected void updateSpecifiedAttributeOverrides() {
ListIterator<JavaAttributeOverride> attributeOverrides = specifiedAttributeOverrides();
Iterator<NestableAnnotation> resourceAttributeOverrides = this.relavantResourceAttributeOverrides();
while (attributeOverrides.hasNext()) {
JavaAttributeOverride attributeOverride = attributeOverrides.next();
if (resourceAttributeOverrides.hasNext()) {
attributeOverride.update((AttributeOverrideAnnotation) resourceAttributeOverrides.next());
}
else {
removeSpecifiedAttributeOverride_(attributeOverride);
}
}
while (resourceAttributeOverrides.hasNext()) {
addSpecifiedAttributeOverride(buildAttributeOverride((AttributeOverrideAnnotation) resourceAttributeOverrides.next()));
}
}
protected Iterator<NestableAnnotation> relavantResourceAttributeOverrides() {
Iterator<NestableAnnotation> resourceAttributeOverrides =
this.javaResourcePersistentMember.annotations(
AttributeOverrideAnnotation.ANNOTATION_NAME,
AttributeOverridesAnnotation.ANNOTATION_NAME);
return new FilteringIterator<NestableAnnotation>(resourceAttributeOverrides) {
@Override
protected boolean accept(NestableAnnotation o) {
String overrideName = ((AttributeOverrideAnnotation) o).getName();
return overrideName != null && getOwner().isRelevant(overrideName);
}
};
}
protected int resourceIndexOf(JavaAttributeOverride specifiedAttributeOverride) {
Iterator<NestableAnnotation> overrideAnnotations = this.javaResourcePersistentMember.annotations(
AttributeOverrideAnnotation.ANNOTATION_NAME,
AttributeOverridesAnnotation.ANNOTATION_NAME);
return CollectionTools.indexOf(
overrideAnnotations,
specifiedAttributeOverride.getOverrideAnnotation());
}
protected JavaAttributeOverride buildAttributeOverride(AttributeOverrideAnnotation attributeOverrideResource) {
JavaAttributeOverride attributeOverride = getJpaFactory().buildJavaAttributeOverride(this, createAttributeOverrideOwner());
attributeOverride.initialize(attributeOverrideResource);
return attributeOverride;
}
protected JavaAttributeOverride buildVirtualAttributeOverride(String attributeOverrideName) {
return buildAttributeOverride(buildVirtualAttributeOverrideAnnotation(attributeOverrideName));
}
protected VirtualAttributeOverrideAnnotation buildVirtualAttributeOverrideAnnotation(String attributeOverrideName) {
Column column = resolveOverriddenColumn(attributeOverrideName);
return new VirtualAttributeOverrideAnnotation(this.javaResourcePersistentMember, attributeOverrideName, column);
}
private Column resolveOverriddenColumn(String attributeOverrideName) {
return getOwner().resolveOverriddenColumn(attributeOverrideName);
}
protected void updateVirtualAttributeOverrides() {
for (String name : CollectionTools.iterable(allOverridableAttributeNames())) {
JavaAttributeOverride attributeOverride = getAttributeOverrideNamed(name);
if (attributeOverride == null) {
addVirtualAttributeOverride(buildVirtualAttributeOverride(name));
}
else if (attributeOverride.isVirtual()) {
attributeOverride.update(buildVirtualAttributeOverrideAnnotation(name));
}
}
Collection<String> attributeNames = CollectionTools.collection(allOverridableAttributeNames());
//remove any default mappings that are not included in the attributeNames collection
for (JavaAttributeOverride attributeOverride : CollectionTools.iterable(virtualAttributeOverrides())) {
if (!attributeNames.contains(attributeOverride.getName())
|| containsSpecifiedAttributeOverride(attributeOverride.getName())) {
removeVirtualAttributeOverride(attributeOverride);
}
}
}
//******************** Code Completion *************************
@Override
public Iterator<String> javaCompletionProposals(int pos, Filter<String> filter, CompilationUnit astRoot) {
Iterator<String> result = super.javaCompletionProposals(pos, filter, astRoot);
if (result != null) {
return result;
}
for (JavaAttributeOverride override : CollectionTools.iterable(this.attributeOverrides())) {
result = override.javaCompletionProposals(pos, filter, astRoot);
if (result != null) {
return result;
}
}
return null;
}
//********** Validation ********************************************
@Override
public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
super.validate(messages, reporter, astRoot);
for (Iterator<JavaAttributeOverride> stream = this.attributeOverrides(); stream.hasNext();) {
stream.next().validate(messages, reporter, astRoot);
}
}
public TextRange getValidationTextRange(CompilationUnit astRoot) {
Annotation annotation =
this.javaResourcePersistentMember.getAnnotation(AttributeOverridesAnnotation.ANNOTATION_NAME);
if (annotation == null) {
annotation = this.javaResourcePersistentMember.getAnnotation(AttributeOverrideAnnotation.ANNOTATION_NAME);
}
return (annotation == null) ?
getOwner().getValidationTextRange(astRoot)
: annotation.getTextRange(astRoot);
}
// ********** attribute override owner **********
protected class AttributeOverrideOwner implements JavaAttributeOverride.Owner {
public Column resolveOverriddenColumn(String attributeName) {
if (attributeName == null) {
return null;
}
return GenericJavaAttributeOverrideContainer.this.resolveOverriddenColumn(attributeName);
}
public boolean isVirtual(BaseOverride override) {
return GenericJavaAttributeOverrideContainer.this.virtualAttributeOverrides.contains(override);
}
public BaseOverride setVirtual(boolean virtual, BaseOverride attributeOverride) {
return GenericJavaAttributeOverrideContainer.this.setAttributeOverrideVirtual(virtual, (JavaAttributeOverride) attributeOverride);
}
public TypeMapping getTypeMapping() {
return getOwner().getTypeMapping();
}
public Iterator<String> allOverridableAttributeNames() {
return GenericJavaAttributeOverrideContainer.this.allOverridableAttributeNames();
}
public String getPossiblePrefix() {
return getOwner().getPossiblePrefix();
}
public boolean tableNameIsInvalid(String tableName) {
return getOwner().tableNameIsInvalid(tableName);
}
public Iterator<String> candidateTableNames() {
return getOwner().candidateTableNames();
}
public String getDefaultTableName() {
return getOwner().getDefaultTableName();
}
public Table getDbTable(String tableName) {
return getOwner().getDbTable(tableName);
}
public IMessage buildColumnTableNotValidMessage(BaseOverride override, BaseColumn column, TextRange textRange) {
return getOwner().buildColumnTableNotValidMessage(override, column, textRange);
}
public IMessage buildColumnUnresolvedNameMessage(BaseOverride override, NamedColumn column, TextRange textRange) {
return getOwner().buildColumnUnresolvedNameMessage(override, column, textRange);
}
}
}