blob: ed467246976646284f686c682c90c5eee15e0de2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 Oracle. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0, which accompanies this distribution
* and is available at https://www.eclipse.org/legal/epl-2.0/.
*
* Contributors:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.jpa.core.internal.jpa2_1.resource.java.source;
import java.util.Arrays;
import java.util.Vector;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jpt.common.core.internal.utility.jdt.AnnotatedElementAnnotationElementAdapter;
import org.eclipse.jpt.common.core.internal.utility.jdt.AnnotationStringArrayExpressionConverter;
import org.eclipse.jpt.common.core.internal.utility.jdt.CombinationIndexedDeclarationAnnotationAdapter;
import org.eclipse.jpt.common.core.internal.utility.jdt.ConversionDeclarationAnnotationElementAdapter;
import org.eclipse.jpt.common.core.internal.utility.jdt.ElementIndexedAnnotationAdapter;
import org.eclipse.jpt.common.core.internal.utility.jdt.SimpleDeclarationAnnotationAdapter;
import org.eclipse.jpt.common.core.resource.java.JavaResourceAnnotatedElement;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.core.utility.jdt.AnnotatedElement;
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.ExpressionConverter;
import org.eclipse.jpt.common.core.utility.jdt.IndexedAnnotationAdapter;
import org.eclipse.jpt.common.core.utility.jdt.IndexedDeclarationAnnotationAdapter;
import org.eclipse.jpt.common.utility.internal.ObjectTools;
import org.eclipse.jpt.common.utility.internal.collection.ListTools;
import org.eclipse.jpt.common.utility.internal.iterable.IterableTools;
import org.eclipse.jpt.common.utility.iterable.ListIterable;
import org.eclipse.jpt.jpa.core.internal.resource.java.source.SourceQueryAnnotation;
import org.eclipse.jpt.jpa.core.internal.resource.java.source.SourceQueryHintAnnotation;
import org.eclipse.jpt.jpa.core.jpa2_1.resource.java.JPA2_1;
import org.eclipse.jpt.jpa.core.jpa2_1.resource.java.NamedStoredProcedureQueryAnnotation2_1;
import org.eclipse.jpt.jpa.core.jpa2_1.resource.java.StoredProcedureParameterAnnotation2_1;
import org.eclipse.jpt.jpa.core.resource.java.QueryHintAnnotation;
/**
* <code>javax.persistence.NamedStoredProcedureQuery</code>
*/
public final class SourceNamedStoredProcedureQueryAnnotation2_1
extends SourceQueryAnnotation
implements NamedStoredProcedureQueryAnnotation2_1
{
private static final DeclarationAnnotationAdapter DECLARATION_ANNOTATION_ADAPTER = new SimpleDeclarationAnnotationAdapter(ANNOTATION_NAME);
private static final DeclarationAnnotationAdapter CONTAINER_DECLARATION_ANNOTATION_ADAPTER = new SimpleDeclarationAnnotationAdapter(JPA2_1.NAMED_STORED_PROCEDURE_QUERIES);
DeclarationAnnotationElementAdapter<String> procedureNameDeclarationAdapter;
AnnotationElementAdapter<String> procedureNameAdapter;
String procedureName;
TextRange procedureNameTextRange;
final StoredProcedureParameterAnnotationContainer storedProcedureParametersContainer = new StoredProcedureParameterAnnotationContainer();
private DeclarationAnnotationElementAdapter<String[]> resultClassesDeclarationAdapter;
private AnnotationElementAdapter<String[]> resultClassesAdapter;
private final Vector<String> resultClasses = new Vector<String>();
private TextRange resultClassesTextRange;
/**
* TODO: Need to handle fullyQualifiedResultClassName/fqResultClassNameStale for each of the result classes
private final Vector<String> fullyQualifiedResultClassNames = new Vector<String>();
// we need a flag since the f-q name can be null
private boolean fqResultClassNameStale = true;
I think you can model this after what Paul recently did in
org.eclipse.jpt.jaxb.core.internal.resource.java.source.SourceXmlSeeAlsoAnnotation
*/
private DeclarationAnnotationElementAdapter<String[]> resultSetMappingsDeclarationAdapter;
private AnnotationElementAdapter<String[]> resultSetMappingsAdapter;
private final Vector<String> resultSetMappings = new Vector<String>();
private TextRange resultSetMappingsTextRange;
public static SourceNamedStoredProcedureQueryAnnotation2_1 buildSourceNamedStoredProcedureQuery2_1Annotation(
JavaResourceAnnotatedElement parent,
AnnotatedElement element,
int index)
{
IndexedDeclarationAnnotationAdapter idaa = buildNamedStoredProcedureQuery2_1DeclarationAnnotationAdapter(index);
IndexedAnnotationAdapter iaa = buildNamedStoredProcedureQuery2_1AnnotationAdapter(element, idaa);
return new SourceNamedStoredProcedureQueryAnnotation2_1(
parent,
element,
idaa,
iaa);
}
private SourceNamedStoredProcedureQueryAnnotation2_1(
JavaResourceAnnotatedElement parent,
AnnotatedElement element,
IndexedDeclarationAnnotationAdapter daa,
IndexedAnnotationAdapter annotationAdapter)
{
super(parent, element, daa, annotationAdapter);
this.procedureNameDeclarationAdapter = this.buildProcedureNameDeclarationAdapter();
this.procedureNameAdapter = this.buildProcedureNameAdapter();
this.resultClassesDeclarationAdapter = this.buildResultClassesDeclarationAdapter();
this.resultClassesAdapter = this.buildResultClassesAdapter();
this.resultSetMappingsDeclarationAdapter = this.buildResultSetMappingsDeclarationAdapter();
this.resultSetMappingsAdapter = this.buildResultSetMappingsAdapter();
}
public String getAnnotationName() {
return ANNOTATION_NAME;
}
@Override
public void initialize(Annotation astAnnotation) {
super.initialize(astAnnotation);
this.procedureName = this.buildProcedureName(astAnnotation);
this.procedureNameTextRange = this.buildProcedureNameTextRange(astAnnotation);
this.storedProcedureParametersContainer.initializeFromContainerAnnotation(astAnnotation);
this.initializeResultClasses(astAnnotation);
this.resultClassesTextRange = this.buildResultClassesTextRange(astAnnotation);
this.initializeResultSetMappings(astAnnotation);
this.resultSetMappingsTextRange = this.buildResultSetMappingsTextRange(astAnnotation);
}
@Override
public void synchronizeWith(Annotation astAnnotation) {
super.synchronizeWith(astAnnotation);
this.syncProcedureName(this.buildProcedureName(astAnnotation));
this.procedureNameTextRange = this.buildProcedureNameTextRange(astAnnotation);
this.storedProcedureParametersContainer.synchronize(astAnnotation);
this.syncResultClasses(astAnnotation);
this.resultClassesTextRange = this.buildResultClassesTextRange(astAnnotation);
this.syncResultSetMappings(astAnnotation);
this.resultSetMappingsTextRange = this.buildResultSetMappingsTextRange(astAnnotation);
}
// ********** AbstractNamedStoredProcedureQuery2_1Annotation implementation **********
@Override
public String getNameElementName() {
return JPA2_1.NAMED_STORED_PROCEDURE_QUERY__NAME;
}
@Override
public String getHintsElementName() {
return JPA2_1.NAMED_STORED_PROCEDURE_QUERY__HINTS;
}
@Override
public QueryHintAnnotation buildHint(int index) {
return SourceQueryHintAnnotation.buildNamedStoredProcedureQuery2_1QueryHint(this, this.annotatedElement, this.daa, index);
}
// ********** NamedStoredProcedureQuery2_1Annotation implementation **********
String getProcedureNameElementName() {
return JPA2_1.NAMED_STORED_PROCEDURE_QUERY__PROCEDURE_NAME;
}
String getParametersElementName() {
return JPA2_1.NAMED_STORED_PROCEDURE_QUERY__PARAMETERS;
}
public StoredProcedureParameterAnnotation2_1 buildParameter(int index) {
return SourceStoredProcedureParameterAnnotation2_1.buildNamedStoredProcedureQuery2_1Parameter(this, this.annotatedElement, this.daa, index);
}
String getResultClassesElementName() {
return JPA2_1.NAMED_STORED_PROCEDURE_QUERY__RESULT_CLASSES;
}
String getResultSetMappingsElementName() {
return JPA2_1.NAMED_STORED_PROCEDURE_QUERY__RESULT_SET_MAPPINGS;
}
// ***** procedure name
public String getProcedureName() {
return this.procedureName;
}
public void setProcedureName(String procedureName) {
if (ObjectTools.notEquals(this.procedureName, procedureName)) {
this.procedureName = procedureName;
this.procedureNameAdapter.setValue(procedureName);
}
}
private void syncProcedureName(String pName) {
String old = this.procedureName;
this.procedureName = pName;
this.firePropertyChanged(PROCEDURE_NAME_PROPERTY, old, pName);
}
private String buildProcedureName(Annotation astAnnotation) {
return this.procedureNameAdapter.getValue(astAnnotation);
}
public TextRange getProcedureNameTextRange() {
return this.procedureNameTextRange;
}
private TextRange buildProcedureNameTextRange(Annotation astAnnotation) {
return this.getElementTextRange(this.procedureNameDeclarationAdapter, astAnnotation);
}
private DeclarationAnnotationElementAdapter<String> buildProcedureNameDeclarationAdapter() {
return ConversionDeclarationAnnotationElementAdapter.forStrings(this.daa, this.getProcedureNameElementName());
}
private AnnotationElementAdapter<String> buildProcedureNameAdapter() {
return this.buildStringElementAdapter(this.procedureNameDeclarationAdapter);
}
// ***** parameters
public ListIterable<StoredProcedureParameterAnnotation2_1> getParameters() {
return this.storedProcedureParametersContainer.getNestedAnnotations();
}
public int getParametersSize() {
return this.storedProcedureParametersContainer.getNestedAnnotationsSize();
}
public StoredProcedureParameterAnnotation2_1 parameterAt(int index) {
return this.storedProcedureParametersContainer.getNestedAnnotation(index);
}
public StoredProcedureParameterAnnotation2_1 addParameter(int index) {
return this.storedProcedureParametersContainer.addNestedAnnotation(index);
}
public void moveParameter(int targetIndex, int sourceIndex) {
this.storedProcedureParametersContainer.moveNestedAnnotation(targetIndex, sourceIndex);
}
public void removeParameter(int index) {
this.storedProcedureParametersContainer.removeNestedAnnotation(index);
}
// ***** result classes
public ListIterable<String> getResultClasses() {
return IterableTools.cloneLive(this.resultClasses);
}
public int getResultClassesSize() {
return this.resultClasses.size();
}
public String resultClassAt(int index) {
return this.resultClasses.elementAt(index);
}
public void addResultClass(String resultClass) {
this.addResultClass(this.resultClasses.size(), resultClass);
}
public void addResultClass(int index, String resultClass) {
this.resultClasses.add(index, resultClass);
this.writeResultClasses();
}
public void moveResultClass(int targetIndex, int sourceIndex) {
ListTools.move(this.resultClasses, targetIndex, sourceIndex);
this.writeResultClasses();
}
public void removeResultClass(String resultClass) {
this.resultClasses.remove(resultClass);
this.writeResultClasses();
}
public void removeResultClass(int index) {
this.resultClasses.remove(index);
this.writeResultClasses();
}
private void writeResultClasses() {
this.resultClassesAdapter.setValue(this.resultClasses.toArray(new String[this.resultClasses.size()]));
}
private void initializeResultClasses(Annotation astAnnotation) {
String[] astResultClasses = this.resultClassesAdapter.getValue(astAnnotation);
for (int i = 0; i < astResultClasses.length; i++) {
this.resultClasses.add(astResultClasses[i]);
}
}
private void syncResultClasses(Annotation astAnnotation) {
String[] javaResultClasses = this.resultClassesAdapter.getValue(astAnnotation);
this.synchronizeList(Arrays.asList(javaResultClasses), this.resultClasses, RESULT_CLASSES_LIST);
}
private TextRange buildResultClassesTextRange(Annotation astAnnotation) {
return this.getElementTextRange(this.resultClassesDeclarationAdapter, astAnnotation);
}
public boolean resultClassesTouches(int pos) {
return this.textRangeTouches(this.resultClassesTextRange, pos);
}
private DeclarationAnnotationElementAdapter<String[]> buildResultClassesDeclarationAdapter() {
return buildResultClassesArrayAnnotationElementAdapter(this.daa, JPA2_1.NAMED_STORED_PROCEDURE_QUERY__RESULT_CLASSES);
}
private AnnotationElementAdapter<String[]> buildResultClassesAdapter() {
return this.buildAnnotationElementAdapter(this.resultClassesDeclarationAdapter);
}
// ***** result set mappings
public ListIterable<String> getResultSetMappings() {
return IterableTools.cloneLive(this.resultSetMappings);
}
public int getResultSetMappingsSize() {
return this.resultSetMappings.size();
}
public String resultSetMappingAt(int index) {
return this.resultSetMappings.elementAt(index);
}
public void addResultSetMapping(String resultClass) {
this.addResultSetMapping(this.resultSetMappings.size(), resultClass);
}
public void addResultSetMapping(int index, String resultClass) {
this.resultSetMappings.add(index, resultClass);
this.writeResultSetMappings();
}
public void moveResultSetMapping(int targetIndex, int sourceIndex) {
ListTools.move(this.resultSetMappings, targetIndex, sourceIndex);
this.writeResultSetMappings();
}
public void removeResultSetMapping(String resultSetMapping) {
this.resultSetMappings.remove(resultSetMapping);
this.writeResultSetMappings();
}
public void removeResultSetMapping(int index) {
this.resultSetMappings.remove(index);
this.writeResultSetMappings();
}
private void writeResultSetMappings() {
this.resultSetMappingsAdapter.setValue(this.resultSetMappings.toArray(new String[this.resultSetMappings.size()]));
}
private void initializeResultSetMappings(Annotation astAnnotation) {
String[] astResultClasses = this.resultSetMappingsAdapter.getValue(astAnnotation);
for (int i = 0; i < astResultClasses.length; i++) {
this.resultSetMappings.add(astResultClasses[i]);
}
}
private void syncResultSetMappings(Annotation astAnnotation) {
String[] javaResultClasses = this.resultSetMappingsAdapter.getValue(astAnnotation);
this.synchronizeList(Arrays.asList(javaResultClasses), this.resultSetMappings, RESULT_SET_MAPPINGS_LIST);
}
private TextRange buildResultSetMappingsTextRange(Annotation astAnnotation) {
return this.getElementTextRange(this.resultSetMappingsDeclarationAdapter, astAnnotation);
}
public boolean resultSetMappingsTouches(int pos) {
return this.textRangeTouches(this.resultSetMappingsTextRange, pos);
}
private DeclarationAnnotationElementAdapter<String[]> buildResultSetMappingsDeclarationAdapter() {
return buildResultSetMappingsArrayAnnotationElementAdapter(this.daa, JPA2_1.NAMED_STORED_PROCEDURE_QUERY__RESULT_SET_MAPPINGS);
}
private AnnotationElementAdapter<String[]> buildResultSetMappingsAdapter() {
return this.buildAnnotationElementAdapter(this.resultSetMappingsDeclarationAdapter);
}
// **********
private AnnotationElementAdapter<String[]> buildAnnotationElementAdapter(DeclarationAnnotationElementAdapter<String[]> daea) {
return new AnnotatedElementAnnotationElementAdapter<String[]>(this.annotatedElement, daea);
}
private static DeclarationAnnotationElementAdapter<String[]> buildResultClassesArrayAnnotationElementAdapter(
DeclarationAnnotationAdapter annotationAdapter,
String elementName)
{
return buildArrayAnnotationElementAdapter(
annotationAdapter,
elementName,
AnnotationStringArrayExpressionConverter.forTypes());
}
private static DeclarationAnnotationElementAdapter<String[]> buildResultSetMappingsArrayAnnotationElementAdapter(
DeclarationAnnotationAdapter annotationAdapter,
String elementName)
{
return buildArrayAnnotationElementAdapter(
annotationAdapter,
elementName,
AnnotationStringArrayExpressionConverter.forStrings());
}
private static DeclarationAnnotationElementAdapter<String[]> buildArrayAnnotationElementAdapter(
DeclarationAnnotationAdapter annotationAdapter,
String elementName,
ExpressionConverter<String[]> converter)
{
return new ConversionDeclarationAnnotationElementAdapter<String[]>(
annotationAdapter,
elementName,
converter);
}
// ********** stored procedure parameter container **********
/**
* adapt the AnnotationContainer interface to the xml schema's xmlns
*/
class StoredProcedureParameterAnnotationContainer
extends AnnotationContainer<StoredProcedureParameterAnnotation2_1>
{
@Override
protected String getNestedAnnotationsListName() {
return PARAMETERS_LIST;
}
@Override
protected String getElementName() {
return SourceNamedStoredProcedureQueryAnnotation2_1.this.getParametersElementName();
}
@Override
protected String getNestedAnnotationName() {
return StoredProcedureParameterAnnotation2_1.ANNOTATION_NAME;
}
@Override
protected StoredProcedureParameterAnnotation2_1 buildNestedAnnotation(int index) {
return SourceNamedStoredProcedureQueryAnnotation2_1.this.buildParameter(index);
}
}
// ********** misc **********
@Override
public boolean isUnset() {
return super.isUnset() &&
(this.procedureName == null) &&
(this.storedProcedureParametersContainer.isEmpty()) &&
(this.resultClasses.isEmpty()) &&
(this.resultSetMappings.isEmpty());
}
// ********** static methods **********
private static IndexedAnnotationAdapter buildNamedStoredProcedureQuery2_1AnnotationAdapter(
AnnotatedElement annotatedElement,
IndexedDeclarationAnnotationAdapter idaa)
{
return new ElementIndexedAnnotationAdapter(annotatedElement, idaa);
}
private static IndexedDeclarationAnnotationAdapter buildNamedStoredProcedureQuery2_1DeclarationAnnotationAdapter(int index)
{
return new CombinationIndexedDeclarationAnnotationAdapter(
DECLARATION_ANNOTATION_ADAPTER,
CONTAINER_DECLARATION_ANNOTATION_ADAPTER,
index,
ANNOTATION_NAME);
}
}