blob: 40c26b89d3273aa482af0db5275a4630b73f53a7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 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.jpa.core.internal.resource.java.source;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Vector;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jpt.common.core.internal.utility.jdt.ConversionDeclarationAnnotationElementAdapter;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.core.utility.jdt.AnnotationAdapter;
import org.eclipse.jpt.common.core.utility.jdt.AnnotationElementAdapter;
import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationAdapter;
import org.eclipse.jpt.common.core.utility.jdt.DeclarationAnnotationElementAdapter;
import org.eclipse.jpt.common.core.utility.jdt.Type;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable;
import org.eclipse.jpt.common.utility.internal.iterators.CloneListIterator;
import org.eclipse.jpt.jpa.core.resource.java.AnnotationContainer;
import org.eclipse.jpt.jpa.core.resource.java.JavaResourceNode;
import org.eclipse.jpt.jpa.core.resource.java.NestableQueryHintAnnotation;
import org.eclipse.jpt.jpa.core.resource.java.QueryAnnotation;
import org.eclipse.jpt.jpa.core.resource.java.QueryHintAnnotation;
/**
* <ul>
* <li><code>javax.persistence.NamedQuery</code>
* <li><code>javax.persistence.NamedNativeQuery</code>
* </ul>
*/
abstract class SourceQueryAnnotation
extends SourceAnnotation<Type>
implements QueryAnnotation
{
DeclarationAnnotationElementAdapter<String> nameDeclarationAdapter;
AnnotationElementAdapter<String> nameAdapter;
String name;
DeclarationAnnotationElementAdapter<String> queryDeclarationAdapter;
AnnotationElementAdapter<String> queryAdapter;
String query;
final Vector<NestableQueryHintAnnotation> hints = new Vector<NestableQueryHintAnnotation>();
final HintsAnnotationContainer hintsContainer = new HintsAnnotationContainer();
SourceQueryAnnotation(JavaResourceNode parent, Type type,DeclarationAnnotationAdapter daa, AnnotationAdapter annotationAdapter) {
super(parent, type, daa, annotationAdapter);
this.nameDeclarationAdapter = this.buildNameDeclarationAdapter();
this.nameAdapter = this.buildNameAdapter();
this.queryDeclarationAdapter = this.buildQueryDeclarationAdapter();
this.queryAdapter = this.buildQueryAdapter();
}
public void initialize(CompilationUnit astRoot) {
this.name = this.buildName(astRoot);
this.query = this.buildQuery(astRoot);
AnnotationContainerTools.initialize(this.hintsContainer, astRoot);
}
public void synchronizeWith(CompilationUnit astRoot) {
this.syncName(this.buildName(astRoot));
this.syncQuery(this.buildQuery(astRoot));
AnnotationContainerTools.synchronize(this.hintsContainer, astRoot);
}
// ********** BaseNamedQueryAnnotation implementation **********
// ***** name
public String getName() {
return this.name;
}
public void setName(String name) {
if (this.attributeValueHasChanged(this.name, name)) {
this.name = name;
this.nameAdapter.setValue(name);
}
}
private void syncName(String astName) {
String old = this.name;
this.name = astName;
this.firePropertyChanged(NAME_PROPERTY, old, astName);
}
private String buildName(CompilationUnit astRoot) {
return this.nameAdapter.getValue(astRoot);
}
public TextRange getNameTextRange(CompilationUnit astRoot) {
return this.getElementTextRange(this.nameDeclarationAdapter, astRoot);
}
private DeclarationAnnotationElementAdapter<String> buildNameDeclarationAdapter() {
return ConversionDeclarationAnnotationElementAdapter.forStrings(this.daa, this.getNameElementName());
}
private AnnotationElementAdapter<String> buildNameAdapter() {
return this.buildStringElementAdapter(this.nameDeclarationAdapter);
}
abstract String getNameElementName();
// ***** query
public String getQuery() {
return this.query;
}
public void setQuery(String query) {
if (this.attributeValueHasChanged(this.query, query)) {
this.query = query;
this.queryAdapter.setValue(query);
}
}
private void syncQuery(String annotationQuery) {
String old = this.query;
this.query = annotationQuery;
this.firePropertyChanged(QUERY_PROPERTY, old, annotationQuery);
}
private String buildQuery(CompilationUnit astRoot) {
return this.queryAdapter.getValue(astRoot);
}
public TextRange getQueryTextRange(CompilationUnit astRoot) {
return this.getElementTextRange(this.queryDeclarationAdapter, astRoot);
}
private DeclarationAnnotationElementAdapter<String> buildQueryDeclarationAdapter() {
return ConversionDeclarationAnnotationElementAdapter.forStrings(this.daa, this.getQueryElementName());
}
private AnnotationElementAdapter<String> buildQueryAdapter() {
return this.buildStringElementAdapter(this.queryDeclarationAdapter);
}
abstract String getQueryElementName();
// ***** hints
public ListIterator<QueryHintAnnotation> hints() {
return new CloneListIterator<QueryHintAnnotation>(this.hints);
}
Iterable<NestableQueryHintAnnotation> getNestableHints() {
return new LiveCloneIterable<NestableQueryHintAnnotation>(this.hints);
}
public int hintsSize() {
return this.hints.size();
}
public NestableQueryHintAnnotation hintAt(int index) {
return this.hints.get(index);
}
public int indexOfHint(QueryHintAnnotation hint) {
return this.hints.indexOf(hint);
}
private NestableQueryHintAnnotation addHint() {
return this.addHint(this.hints.size());
}
public NestableQueryHintAnnotation addHint(int index) {
return (NestableQueryHintAnnotation) AnnotationContainerTools.addNestedAnnotation(index, this.hintsContainer);
}
NestableQueryHintAnnotation addHint_() {
return this.addHint_(this.hints.size());
}
private NestableQueryHintAnnotation addHint_(int index) {
NestableQueryHintAnnotation hint = this.buildHint(index);
this.hints.add(index, hint);
return hint;
}
void syncAddHint(Annotation astAnnotation) {
int index = this.hints.size();
NestableQueryHintAnnotation hint = this.addHint_(index);
hint.initialize((CompilationUnit) astAnnotation.getRoot());
this.fireItemAdded(HINTS_LIST, index, hint);
}
abstract NestableQueryHintAnnotation buildHint(int index);
void hintAdded(int index, NestableQueryHintAnnotation hint) {
this.fireItemAdded(HINTS_LIST, index, hint);
}
public void moveHint(int targetIndex, int sourceIndex) {
AnnotationContainerTools.moveNestedAnnotation(targetIndex, sourceIndex, this.hintsContainer);
}
NestableQueryHintAnnotation moveHint_(int targetIndex, int sourceIndex) {
return CollectionTools.move(this.hints, targetIndex, sourceIndex).get(targetIndex);
}
public void removeHint(int index) {
AnnotationContainerTools.removeNestedAnnotation(index, this.hintsContainer);
}
NestableQueryHintAnnotation removeHint_(int index) {
return this.hints.remove(index);
}
void syncRemoveHints(int index) {
this.removeItemsFromList(index, this.hints, HINTS_LIST);
}
abstract String getHintsElementName();
// ********** NestableAnnotation implementation **********
/**
* convenience implementation of method from NestableAnnotation interface
* for subclasses
*/
public void moveAnnotation(int newIndex) {
this.getIndexedAnnotationAdapter().moveAnnotation(newIndex);
}
// ********** misc **********
@Override
public boolean isUnset() {
return super.isUnset() &&
(this.name == null) &&
(this.query == null) &&
this.hints.isEmpty();
}
@Override
protected void rebuildAdapters() {
super.rebuildAdapters();
this.nameDeclarationAdapter = this.buildNameDeclarationAdapter();
this.nameAdapter = this.buildNameAdapter();
this.queryDeclarationAdapter = this.buildQueryDeclarationAdapter();
this.queryAdapter = this.buildQueryAdapter();
}
@Override
public void storeOn(Map<String, Object> map) {
super.storeOn(map);
map.put(NAME_PROPERTY, this.name);
this.name = null;
map.put(QUERY_PROPERTY, this.query);
this.query = null;
List<Map<String, Object>> hintsState = this.buildStateList(this.hints.size());
for (NestableQueryHintAnnotation hint : this.getNestableHints()) {
Map<String, Object> hintState = new HashMap<String, Object>();
hint.storeOn(hintState);
hintsState.add(hintState);
}
map.put(HINTS_LIST, hintsState);
this.hints.clear();
}
@Override
public void restoreFrom(Map<String, Object> map) {
super.restoreFrom(map);
this.setName((String) map.get(NAME_PROPERTY));
this.setQuery((String) map.get(QUERY_PROPERTY));
@SuppressWarnings("unchecked")
List<Map<String, Object>> hintsState = (List<Map<String, Object>>) map.get(HINTS_LIST);
for (Map<String, Object> hintState : hintsState) {
this.addHint().restoreFrom(hintState);
}
}
@Override
public void toString(StringBuilder sb) {
sb.append(this.name);
}
// ********** hint container **********
/**
* adapt the AnnotationContainer interface to the override's join columns
*/
class HintsAnnotationContainer
implements AnnotationContainer<NestableQueryHintAnnotation>
{
public Annotation getAstAnnotation(CompilationUnit astRoot) {
return SourceQueryAnnotation.this.getAstAnnotation(astRoot);
}
public String getElementName() {
return SourceQueryAnnotation.this.getHintsElementName();
}
public String getNestedAnnotationName() {
return QueryHintAnnotation.ANNOTATION_NAME;
}
public Iterable<NestableQueryHintAnnotation> getNestedAnnotations() {
return SourceQueryAnnotation.this.getNestableHints();
}
public int getNestedAnnotationsSize() {
return SourceQueryAnnotation.this.hintsSize();
}
public NestableQueryHintAnnotation addNestedAnnotation() {
return SourceQueryAnnotation.this.addHint_();
}
public void syncAddNestedAnnotation(Annotation astAnnotation) {
SourceQueryAnnotation.this.syncAddHint(astAnnotation);
}
public NestableQueryHintAnnotation moveNestedAnnotation(int targetIndex, int sourceIndex) {
return SourceQueryAnnotation.this.moveHint_(targetIndex, sourceIndex);
}
public NestableQueryHintAnnotation removeNestedAnnotation(int index) {
return SourceQueryAnnotation.this.removeHint_(index);
}
public void syncRemoveNestedAnnotations(int index) {
SourceQueryAnnotation.this.syncRemoveHints(index);
}
@Override
public String toString() {
return StringTools.buildToStringFor(this);
}
}
}