All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.neba.api.spi.AnnotatedFieldMapper Maven / Gradle / Ivy

Go to download

Contains all annotations, tag libraries and lifecycle callback interfaces of NEBA. All packages of this API bundle are exported. Change to the API that are not byte code compatible only occur in major revisions.

There is a newer version: 5.2.3
Show newest version
/*
  Copyright 2013 the original author or authors.
  

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 io.neba.api.spi; import org.apache.sling.api.resource.Resource; import org.apache.sling.api.resource.ValueMap; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.Map; /** * OSGi services implementing this interface may customize the mapping of arbitrary fields during * the resource to model mapping of any resource model. *

* The implementing service specifies {@link #getAnnotationType() the annotation it is responsible for} * as well as {@link #getFieldType() the type the mapped fields} must be {@link Class#isAssignableFrom(Class) assignable to}. *

*

* For example, the following service would be responsible for fields annotated with @MyAnnotation * with a type assignable to {@link java.util.Collection}, e.g. List<Resource> or Set<String>. *

*
 * @Component(service = { AnnotatedFieldMapper.class })
 * public class MyFieldMapper implements AnnotatedFieldMapper<Collection, MyAnnotation> {
 *     public Class<? extends Collection> getFieldType() {
 *         return Collection.class;
 *     }
 *
 *     public Class<Annotation> getAnnotationType() {
 *         return MyAnnotation.class;
 *     }
 *
 *     public Collection map(OngoingMapping<Collection, MyAnnotation> ongoingMapping) {
 *         ...
 *     }
 * }
 * 
*

* Custom mappers are always invoked after all of NEBA's standard mappings have occurred, but before * the corresponding value was set on the model's field. They may thus make use of the already resolved * value or choose to provide a different one. *

*

*

* It is crucial for a {@link AnnotatedFieldMapper} to always return a value that is assignment compatible * to the {@link OngoingMapping#getFieldType() field type}, i.e. either of the same or of a more specific type. * It is insufficient to return a type compatible to the {@link #map(AnnotatedFieldMapper.OngoingMapping) mapping methods} * return type declaration. This return type only represents the type any returned value must be compatible to.
* For instance, if a mapper is responsible for {@link java.util.Collection}, it must take care to return the field's actual * collection type, e.g. {@link java.util.List} or {@link java.util.Set}. Otherwise, an exception will arise. *

*

*

* Implementations must never store any contextual data provided by the * {@link AnnotatedFieldMapper.OngoingMapping} * as this data stems from arbitrary OSGi bundles with independent life cycles. * Storing any data would result in a class loader / memory leak when these bundles change. *

* * @param the super type of the {@link java.lang.reflect.Field#getType() field type} * of the mapped type. * @param the exact type of the annotation this mapper is responsible for. * @author Olaf Otto * @since 1.0.0 */ public interface AnnotatedFieldMapper { /** * Represents the contextual data of a field mapping during a resource to model mapping. * * @param the {@link Field#getType() field type} * @param the {@link Annotation type} * @author Olaf Otto */ interface OngoingMapping { /** * @return The currently resolved value of the field, * or null if no value could be resolved for the field. This value * has not been set to the {@link #getField() field} at this point. */ @CheckForNull FieldType getResolvedValue(); /** * @return The instance of {@link #getAnnotationType() the annotation this mapper is registered for}. * Never null. */ @Nonnull AnnotationType getAnnotation(); /** * @return The mapped model. At this point, the mapping is still incomplete and * no post-processors have been invoked on the model. Never null. */ @Nonnull Object getModel(); /** * @return the mapped field. Never null. The field's value was not changed at this point, i.e. it is likely to * deviate from {@link #getResolvedValue()}. Note: do not rely on this {@link java.lang.reflect.Field#getType() field's type} * but use the {@link #getFieldType() provided field type} instead, as these types may be different, for instance in case * of {@link io.neba.api.resourcemodels.Lazy} fields. */ @Nonnull Field getField(); /** * @return All annotations (including meta-annotations, i.e. annotations of annotations) present on the field. * Never null. */ @Nonnull Map, Annotation> getAnnotationsOfField(); /** * @return The mapped type of the field. Note: In case the field is {@link io.neba.api.resourcemodels.Lazy}, this * type is the component type, i.e. the type targeted by the optional field. However, field mappers * are not applied optional fields but to the subsequent mapping, when the {@link io.neba.api.resourcemodels.Lazy#get() lazy value is actually mapped}. * Never null. */ @Nonnull Class getFieldType(); /** * @return the generic type parameter of the {@link #getFieldType() field type}, or null if * no such parameter exists. */ @CheckForNull Class getFieldTypeParameter(); /** * @return the repository path that shall be resolved to the field's value, as determined by the * field name or {@link io.neba.api.annotations.Path path annotation}. Placeholders * in the path are resolved at this point. Never null. */ @Nonnull String getRepositoryPath(); /** * @return The resource that is mapped to the model. Never null, but may be a synthetic resource. */ @Nonnull Resource getResource(); /** * @return The {@link org.apache.sling.api.resource.ValueMap} representation of the {@link #getResource() resource}. * This value map does support primitive types, e.g. int. May be null if the resource * has no properties, e.g. if it is synthetic. */ @CheckForNull ValueMap getProperties(); } /** * @return never null. */ @Nonnull Class getFieldType(); /** * @return never null. */ @Nonnull Class getAnnotationType(); /** * @param ongoingMapping never null. * @return The value to be set on the mapped field during the resource to model mapping. * Must return a value that is assignment-compatible to {@link OngoingMapping#getFieldType()}. * Can be null. */ @CheckForNull FieldType map(OngoingMapping ongoingMapping); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy