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

io.neba.api.resourcemodels.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.resourcemodels;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;

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>. *

*
 * @Service
 * @Component(immediate = true)
 * public class MyFieldMapper<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 io.neba.api.resourcemodels.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 */ 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. */ FieldType getResolvedValue(); /** * @return The instance of {@link #getAnnotationType() the annotation this mapper is registered for}. * Never null. */ 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. */ 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.Optional} fields. */ Field getField(); /** * @return All annotations (including meta-annotations, i.e. annotations of annotations) present on the field. * Never null. */ Map, Annotation> getAnnotationsOfField(); /** * @return The mapped type of the field. Note: In case the field is {@link io.neba.api.resourcemodels.Optional}, 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 Optional#get() optional value is actually mapped. * Never null. */ Class getFieldType(); /** * @return the generic type parameter of the {@link #getFieldType() field type}, or null if * no such parameter exists. */ 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. */ String getRepositoryPath(); /** * @return The resource that is mapped to the model. Never null, but may be a synthetic resource. */ 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. {@link int.class}. May be null if the resource * has no properties, e.g. if it is synthetic. */ ValueMap getProperties(); } /** * @return never null. */ Class getFieldType(); /** * @return never null. */ 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. */ FieldType map(OngoingMapping ongoingMapping); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy