Skip to content
Snippets Groups Projects
Commit eefb44b4 authored by Simon Barner's avatar Simon Barner
Browse files

- Revise and document IAnnotationValueProvider API and add some TODOs for further refinement

- Provide generic abstract base classes:
  - ValueProviderBase -> for generic annotated specifications
  - SinglePrimitiveAttributeValueProviderBase, for annotated specifications whose storage is implemented by a single primitive attribute (Double, Integer, String, etc.)
parent 5e8b053e
No related branches found
No related tags found
No related merge requests found
......@@ -167,7 +167,7 @@ public final class AnnotationEntry {
Class<? extends IAnnotatedSpecification> clazz, Object parent) {
for(IAnnotatedSpecification s : specificationsList) {
if(clazz.isInstance(s)) {
return providerSpecMapping.get(clazz).getEditElement(viewer, clazz, parent);
return providerSpecMapping.get(clazz).getEditingSupport(viewer, clazz, parent);
}
}
......
......@@ -82,15 +82,24 @@ public class AnnotationValueService extends
List<? extends IModelElement> allChildren =
getAllChildren(root, element.getClass(),
annotationProvider.filterOut());
annotationProvider.excludeModelElementTypeFromAnnotatedSpecification());
for(final IModelElement e : allChildren) {
IAnnotatedSpecification annotatedSpecification =
EcoreUtils.pickFirstInstanceOf(annotationProvider.getClazz(),
EcoreUtils.pickFirstInstanceOf(
annotationProvider.getAnnotationClazz(),
e.getSpecifications());
if(annotatedSpecification == null) {
annotatedSpecification =
annotationProvider.addNewSpecToModelElement(e);
try {
annotatedSpecification =
annotationProvider
.getAnnotatedSpecificationForModelElement(e);
} catch(Exception ex) {
System.out
.println("Error instantating new annotation: createAnnotatedSpecificationForModelElement() failed for " +
annotationProvider.getAnnotationClazz() + ".");
return;
}
}
boolean add = true;
......@@ -122,11 +131,11 @@ public class AnnotationValueService extends
* filterOut list
*/
private <S, T> List<? extends IModelElement> getAllChildren(EObject element,
Class<? extends IModelElement> type, List<Class<? extends EObject>> filterOut) {
Class<? extends IModelElement> type, List<Class<? extends EObject>> modelElementTypesExcludedFromAnnotatedSpecification) {
List<? extends IModelElement> results = new ArrayList<IModelElement>();
if(filterOut != null)
getAllChildren2(element, type, filterOut, results);
if(modelElementTypesExcludedFromAnnotatedSpecification != null)
getAllChildren2(element, type, modelElementTypesExcludedFromAnnotatedSpecification, results);
else
results = EcoreUtils.getChildrenWithType(element, type);
return results;
......@@ -136,21 +145,21 @@ public class AnnotationValueService extends
/** depth search for desired elements */
@SuppressWarnings("unchecked")
private <T, S> void getAllChildren2(EObject element, Class<? extends IModelElement> type,
List<Class<? extends EObject>> filterOut, final List<T> results) {
List<Class<? extends EObject>> modelElementTypesExcludedFromAnnotatedSpecification, final List<T> results) {
EList<EObject> eContents = element.eContents();
for(EObject o : eContents) {
if(type.isInstance(o)) {
results.add((T)o);
getAllChildren2(o, type, filterOut, results);
getAllChildren2(o, type, modelElementTypesExcludedFromAnnotatedSpecification, results);
} else {
boolean filter = false;
for(Class<?> c : filterOut) {
for(Class<?> c : modelElementTypesExcludedFromAnnotatedSpecification) {
if(c.isInstance(o))
filter = true;
}
if(!filter)
getAllChildren2(o, type, filterOut, results);
getAllChildren2(o, type, modelElementTypesExcludedFromAnnotatedSpecification, results);
}
}
}
......
......@@ -24,14 +24,41 @@ import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.EditingSupport;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.base.ui.annotation.view.GenericAnnotationView;
import org.fortiss.tooling.kernel.service.base.IEObjectAware;
/**
* Interface for {@link IAnnotatedSpecification}s. It defines the methods that need to be
* implemented by a value provider to define the handling of the stored data and to retrieve
* information relevant to the UI, like the support for complex value types.
* Value provider interface for {@link IAnnotatedSpecification}s that
*
* @author eder, diewald
* <p>
* <ul>
* <li>establishes the link between the model (data storage) and the UI (data exchange and
* conversion)</li>
* <li>provides related annotation data-type specific operations, e.g. factory methods to create
* <ul>
* <li>new annotation instances</li>
* <li>{@link EditingSupport} UI controls for the generic table-based {@link GenericAnnotationView}</li>
* </ul>
* </ul>
*
* Concrete annotations need to provide specific implementations of this interface to perform the
* data exchange and conversion, and to provide the required factory methods.
* </p>
*
* <p>
* The interface / some of its methods take two template parameters
*
* <ul>
* <li><tt>T</tt>: Meta-model type of the specification, i.e. the particular subclass of
* {@link IAnnotatedSpecification} supported by the respective implementation of this
* {@link IAnnotationValueProvider} interface.</li>
* <li><tt>U</tt>: Data type used in the UI to support the respective annotation. For <tt>U</tt>, a
* reasonable {@code toString()} implementation must be provided that is used by the framework to
* render the value of the annotation in text-based editing support UI controls.</li>
* </ul>
* </p>
*
* @author eder, diewald, barner
* @author $Author$
* @version $Rev$
* @ConQAT.Rating YELLOW Hash: 8BE6A1ECB76A0AD4141B7EE11CAE21DA
......@@ -43,44 +70,85 @@ public interface IAnnotationValueProvider<T extends IAnnotatedSpecification> ext
* Returns a boolean whether the implemented specification supports storing multiple values.
* This method is used to handle these classes in the view part in a simpler manner.
*/
// TODO: Review
public boolean allowsMultipleValues();
/** Returns the name of the Annotation for 'specification' */
/**
* Returns the name of the annotation (e.g., used as column label in the table-based
* {@link GenericAnnotationView}).
*/
public String getAnnotationName(T specification);
/** Sets a new name for the annotation and overrides the old one */
public void setAnnotationName(String name, T specification) throws IllegalArgumentException;
/**
* Sets a new name for the annotation (e.g., used as column label in the table-based
* {@link GenericAnnotationView}). The return value indicates if the rename operation was
* successful.
*/
public boolean setAnnotationName(String name, T specification);
/** Returns the value of the annotation for 'specification' */
public <V> V getAnnotationValue(T specification);
/** Returns the value of the annotation in the user-specified data-type. */
public <U> U getAnnotationValue(T specification);
/** Sets a new value for the annotation. */
public <V> void setAnnotationValue(V value, T specification) throws IllegalArgumentException;
/**
* Sets a new value for the annotation, taking an instance the user-specified data type has an
* input.
*
* @throws Exception
* is thrown if the conversion from the UI internal value representation ({@code U})
* to the respective specialization of {@link IAnnotatedSpecification} has failed,
* or if this operation is not available.
*/
public <U> void setAnnotationValue(U value, T specification) throws Exception;
/** Sets a new value in the annotation from a {@link String} representation. */
/**
* Sets a new value in the annotation from a {@link String} representation.
*
* @throws Exception
* is thrown if the conversion from {@link String} to the respective specialization
* of {@link IAnnotatedSpecification} has failed, or if this operation is not
* available.
*/
public void setAnnotationValue(String value, T specification) throws Exception;
/**
* If this method does not return null, a combo box is provided with the specific return values
*/
// TODO: Review / Remove from interface, implement {@link EditingSupport} for Enums instead
public List<String> getFixedValues();
/**
* Returns a custom EditingSupport element for the annotation view
* Returns a custom {@link EditingSupport} support element for the table-based
* {@link GenericAnnotationView}. In case {@code null} is returned, the annotation framework
* tries to fall back to one of the stand {@link EditingSupport}s instead.
*/
public EditingSupport getEditElement(ColumnViewer viewer,
public EditingSupport getEditingSupport(ColumnViewer viewer,
Class<? extends IAnnotatedSpecification> class1, Object parent);
/**
* Adds a new {@link IAnnotatedSpecification} of type T to the given model element and returns
* it
* Factory method that creates a new {@link IAnnotatedSpecification} specialization of type T to
* the given model {@code element} and returns a reference to it.
*
* In case the annotation already exists in the model, this method does not create a new object,
* but returns the existing one.
*
* @throws Exception
* is thrown if no existing element could be retrieved, and the creation of a new
* element has failed.
*/
public T addNewSpecToModelElement(IModelElement element);
public T getAnnotatedSpecificationForModelElement(IModelElement element) throws Exception;
/** Returns the class of T */
public Class<T> getClazz();
/**
* Returns the concrete specialization {@code T} of {@link IAnnotatedSpecification} supported by
* this specialization of {@link IAnnotationValueProvider}.
*/
public Class<T> getAnnotationClazz();
/** Returns a List of Objects which children will not have {@link IAnnotatedSpecification}s */
public List<Class<? extends EObject>> filterOut();
/**
* Returns a {@link List} of model element types which will not have the
* {@link IAnnotatedSpecification} managed by this {@link IAnnotationValueProvider}, refining
* the registration of the respective {@link IAnnotatedSpecification} in the
* {@code org.fortiss.tooling.base.ui.annotationViewPart} extension point.
*/
public List<Class<? extends EObject>> excludeModelElementTypeFromAnnotatedSpecification();
}
/*--------------------------------------------------------------------------+
$Id$
| |
| Copyright 2014 ForTISS GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.ui.annotation.valueprovider;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
import org.fortiss.tooling.base.model.element.IModelElement;
import org.fortiss.tooling.base.model.element.IModelElementSpecification;
/**
* Base class for {@link IAnnotationValueProvider}s for {@link IAnnotatedSpecification}s that
* contain only a single (primitive type) attribute.
*
* @author barner
* @author $Author$
* @version $Rev$
* @ConQAT.Rating RED Hash:
*/
public abstract class SinglePrimitiveAttributeValueProviderBase<T extends IAnnotatedSpecification>
extends ValueProviderBase<T> {
/**
* {@link EClass} of {@link IAnnotatedSpecification} managed by this
* {@link IAnnotationValueProvider}.
*/
final private EClass annotatedSpecificationEClass;
/**
* {@link EFactory} of ECore model that contains {@link IAnnotatedSpecification} identified by
* {@code annotatedSpecificationEClass} (used to create new instances of the annotation).
*/
final private EFactory eFactory;
/**
* {@link Class} of the primitive attribute used to implemented the storage of the underlying
* {@link IAnnotatedSpecification}.
*/
final private Class<?> attributeClazz;
/**
* String representation of default value used to initialize the primitive attribute of the
* underlying {@link IAnnotatedSpecification}. If it is {@code null}, the default constructor
* of the data type identified by {@code attributeClazz} is used to create the attribute
* instance.
*/
final String attributeDefaultValue;
/**
* Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
* whose storage is implemented by a single, primitive attribute. Unless the type of the
* attribute (contained in {@code attributeClazz} is {@link Double} or {@link Integer}, this
* constructor assumes that the attribute is default constructible. Otherwise, the new instances
* of the attribute are initialized to {@code 0}.
*/
public SinglePrimitiveAttributeValueProviderBase(EClass annotatedSpecificationEClass,
EFactory eFactory, Class<?> attributeClazz) {
this(annotatedSpecificationEClass, eFactory, attributeClazz,
getDefaultValueInitializer(attributeClazz));
}
/**
* Constructs a {@link IAnnotationValueProvider} for a {@link IAnnotatedSpecification} that
* whose storage is implemented by a single, primitive attribute. The constructor assumes that
* the attribute type has a constructor that can initialize the new instance from a
* {@link String}.
*/
public SinglePrimitiveAttributeValueProviderBase(EClass annotatedSpecificationEClass,
EFactory eFactory, Class<?> attributeClazz, final String attributeDefaultValue) {
this.annotatedSpecificationEClass = annotatedSpecificationEClass;
this.eFactory = eFactory;
this.attributeClazz = attributeClazz;
this.attributeDefaultValue = attributeDefaultValue;
}
/**
* Returns the initializer {@link String} in case this {@link IAnnotationValueProvider} is
* constructed without specifying a default value, i.e. using
* {@link #SinglePrimitiveAttributeValueProviderBase(EClass, EFactory, Class)}, or {@code null}
* that indicates that the attribute type's default constructor should be used to initialize new
* instances of the {@link IAnnotatedSpecification}'s attribute.
*/
private static String getDefaultValueInitializer(Class<?> attributeClazz) {
if(attributeClazz.equals(Double.class) || attributeClazz.equals(Integer.class)) {
return "0";
}
return null;
}
/**
* Returns the structural {@link EStructuralFeature} of the attribute used to implement the
* storage of the underlying {@link IAnnotatedSpecification}. This implementation returns the
* first attribute of the annotation identified by {@code annotatedSpecificationEClass}.
*/
private EStructuralFeature getStructuralFeature() {
return annotatedSpecificationEClass.getEStructuralFeatures().get(0);
}
/** {@inheritDoc} */
@Override
public void setAnnotationValue(String value, T specification) throws Exception {
specification.eSet(getStructuralFeature(),
attributeClazz.getDeclaredConstructor(String.class).newInstance(value));
}
/** {@inheritDoc} */
@Override
public <U> void setAnnotationValue(U value, T specification) throws Exception {
specification.eSet(getStructuralFeature(), value);
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override
public <U> U getAnnotationValue(T specification) {
return (U)specification.eGet(getStructuralFeature());
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override
public T getAnnotatedSpecificationForModelElement(IModelElement element) throws Exception {
// Return existing annotation
for(IModelElementSpecification specification : element.getSpecifications()) {
if(annotatedSpecificationEClass.equals(specification.eClass())) {
return (T)specification;
}
}
// Create annotation
T specification = (T)eFactory.create(annotatedSpecificationEClass);
Object attributeValue;
// Create annotation attribute
if(attributeDefaultValue != null) {
attributeValue =
attributeClazz.getDeclaredConstructor(String.class).newInstance(
attributeDefaultValue);
} else {
attributeValue = attributeClazz.newInstance();
}
specification.eSet(getStructuralFeature(), attributeValue);
// Hook specification to model element
element.addSpecification(specification);
return specification;
}
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override
public Class<T> getAnnotationClazz() {
return (Class<T>)annotatedSpecificationEClass.getClass();
}
}
/*--------------------------------------------------------------------------+
$Id$
| |
| Copyright 2014 ForTISS GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.tooling.base.ui.annotation.valueprovider;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.EditingSupport;
import org.fortiss.tooling.base.model.element.IAnnotatedSpecification;
/**
* Base class for {@link IAnnotationValueProvider}s.
*
* @author diewald
* @author $Author$
* @version $Rev$
* @ConQAT.Rating RED Hash:
*/
public abstract class ValueProviderBase<T extends IAnnotatedSpecification> implements
IAnnotationValueProvider<T> {
/** {@inheritDoc} */
@Override
public boolean setAnnotationName(String name, T specification) {
// Renaming this annotation is not supported.
return false;
}
/** {@inheritDoc} */
@Override
public void setAnnotationValue(String value, T specification) throws Exception {
throw new Exception(
"setAnnotationValue(String) is not supported / has not been implemented for annotations of type " +
getClass());
}
/** {@inheritDoc} */
@Override
public <U> void setAnnotationValue(U value, T specification) throws Exception {
throw new Exception(
"setAnnotationValue(U) is not supported / has not been implemented for annotations of type " +
getClass());
}
/** {@inheritDoc} */
@Override
public boolean allowsMultipleValues() {
return false;
}
/** {@inheritDoc} */
@Override
public List<String> getFixedValues() {
return null;
}
/** {@inheritDoc} */
@Override
public EditingSupport getEditingSupport(ColumnViewer viewer,
Class<? extends IAnnotatedSpecification> class1, Object parent) {
return null;
}
/** {@inheritDoc} */
@Override
public List<Class<? extends EObject>> excludeModelElementTypeFromAnnotatedSpecification() {
return null;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment