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

jakarta.faces.model.FacesDataModel Maven / Gradle / Ivy

There is a newer version: 11.0.0-M4
Show newest version
/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package jakarta.faces.model;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.Set;

import jakarta.faces.component.UIData;
import jakarta.inject.Qualifier;

/**
 * 
*

* The presence of this annotation on a class automatically registers the class with the runtime as a {@link DataModel} * that is capable of wrapping a type indicated by the {@link FacesDataModel#forClass()} attribute. * *

* The runtime must maintain a collection of these {@link DataModel}s such that {@link UIData} and other components * defined by the Jakarta Server Faces specification can query the runtime for a suitable {@link DataModel} wrapper * (adapter) for the type of their value. This has to be done after all wrappers for specific types such as * {@link Set} are tried, but before the {@link ScalarDataModel} is selected as the wrapper. See * {@link UIData#getValue()}. * *

* This query must work as follows: * *

* For an instance of type Z that is being bound to a UIData component or other component * defined by the Jakarta Server Faces specification that utilizes DataModel, the query for that type must * return the most specific DataModel that can wrap Z. * *

* This most specific DataModel is defined as the DataModel that is obtained by first sorting the collection in * which the registered DataModels are stored (for details on this sorting see below) and then * iterating through the sorted collection from beginning to end and stopping this iteration at the first match where * for the class ZZ wrapped by the DataModel (as indicated by the {@link FacesDataModel#forClass()} * attribute) it holds that ZZ.isAssignableFrom(Z). This match is then taken as the most specific * DataModel. * *

* The sorting must be done as follows: * *

* Sort on the class wrapped by a DataModel that is stored in the above mentioned collection such that for any 2 classes * X and Y from this collection, if an object of X is an instanceof * an object of Y, X appears in the collection before Y. The * collection's sorting is otherwise arbitrary. In other words, subclasses come before their superclasses. * *

* For example: * *

* Given class B, class A extends B and class Q, two possible orders are; *

    *
  1. {A, B, Q} *
  2. {Q, A, B} *
* *

* The only requirement here is that A appears before B, since A is a subclass of * B. * *

* The specification does not define a public method to obtain an instance of the "most specific DataModel for a given * type". Such an instance can be obtained using code similar to the following. *

* *
 * 
 *   @SuppressWarnings("unchecked")
 *   public <T> DataModel<T> createDataModel(Class<T> forClass, Object value) {
 *       class LocalUIData extends UIData {
 *           @Override
 *           public DataModel<?> getDataModel() {
 *               return super.getDataModel();
 *           }
 *       }
 *       LocalUIData localUIData = new LocalUIData();
 *       localUIData.setValue(value);
 *
 *       return (DataModel<T>) localUIData.getDataModel();
 *   }
 * 
 * 
* *

* For example: *

* *
 * 
 * public class Child1 {
 *
 * }
 * 
 * 
* * and * *
 * 
 * package test.faces23;
 *
 * @FacesDataModel(forClass = Child1.class)
 * public class Child1Model<E> extends DataModel<E> {
 *
 *    @Override
 *    public int getRowCount() {
 *        return 0;
 *    }
 *
 *    @Override
 *    public E getRowData() {
 *        return null;
 *    }
 *
 *    @Override
 *    public int getRowIndex() {
 *        return 0;
 *    }
 *
 *    @Override
 *    public Object getWrappedData() {
 *        return null;
 *    }
 *
 *    @Override
 *    public boolean isRowAvailable() {
 *        return false;
 *    }
 *
 *    @Override
 *    public void setRowIndex(int arg0) {
 *
 *    }
 *
 *    @Override
 *    public void setWrappedData(Object arg0) {
 *
 *    }
 * }
 * 
 * 
* *

* Then the following must work: *

* *
 * 
 * DataModel<Child1> myModel = createDataModel(Child1.class, new Child1());
 * assert myModel instanceof Child1Model;
 * System.out.println(myModel.getClass());
 * 
 * 
* *

* The result printed should be e.g.: "class * test.faces23.Child1Model" *

* *
* */ @Retention(RUNTIME) @Target(TYPE) @Inherited @Qualifier public @interface FacesDataModel { /** *

* The value of this annotation attribute is taken to be the type that the DataModel that is annotated with this * annotation is able to wrap. *

* * @return the type that the DataModel that is annotated with this annotation is able to wrap */ Class forClass() default Object.class; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy