/*
* Copyright (C) 2012 Red Hat, Inc. and/or its affiliates.
*
* 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.jboss.errai.ui.shared.api.annotations;
import static org.jboss.errai.ui.shared.api.annotations.DataField.ConflictStrategy.USE_TEMPLATE;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Inject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.Widget;
import jsinterop.annotations.JsType;
/**
* <p>
* Indicates that the target Java reference (field, method parameter, or constructor parameter) in a {@link Templated}
* component corresponds to an HTML element in the class's companion template. <b>This annotation can only be used in
* classes that have been annotated with {@link Templated}, or in super-classes of such types.</b>
* <p>
* A field or parameter annotated with {@link DataField} should be one of the following:
* <ul>
* <li>A {@link Templated} component
* <li>A native {@link JsType} wrapping an HTML element
* <li>An Elemental HTML element wrapper
* <li>A gwt-user {@link Element}
* <li>A {@link Widget}
*
* <p>
* The matching of Java references to HTML elements is performed as follows:
* <ol>
* <li>A <i>name</i> for the Java reference is determined. If the {@code @DataField} annotation has a {@link #value}
* argument, it is used as the reference name. For fields, the default name is the field name. Method and constructor
* parameters have no default name, so they must always specify a value.
* <li>If there is an element in the HTML template with attribute <tt>data-field=<i>name</i></tt>, the Java reference
* will point to this element. If there is more than one such element, the Java reference will point to the first.
* <li>Otherwise, if there is an element in the HTML template with attribute <tt>id=<i>name</i></tt>, the Java reference
* will point to this element. If there is more than one such element, the Java reference will point to the first.
* <li>Otherwise, if there is an element in the HTML template with a CSS style class <tt><i>name</i></tt>, the Java
* reference will point to this element. If there is more than one such element, the Java reference will point to the
* first. For elements with more than one CSS style, each style name is considered individually. For example:
*
* <pre>
* <div class="eat drink be-merry">
* </pre>
*
* matches Java references named <tt>eat</tt>, <tt>drink</tt>, or <tt>be-merry</tt>.
* <li>If no matching element is found by this point, it is an error.
* </ol>
* <p>
* If more than one Java reference matches the same HTML element in the template, it is an error. For example, given a
* template containing the element <tt><div class="eat drink be-merry"></tt>, the following Java code is in error:
*
* <pre>
* @Templated
* public class ErroneousTemplate extends Composite {
* @Inject
* @DataField
* private Label eat;
*
* @Inject
* @DataField
* private Label drink;
* }
* </pre>
*
* because both fields <tt>eat</tt> and <tt>drink</tt> refer to the same HTML <tt>div</tt> element.
* <p>
* When used on a method or constructor parameter, this must be accompanied by a corresponding {@link Inject}
* annotation; however, when used on a field, construction may be performed manually or via {@link Inject}.
*
* <p>
* <b>See also:</b> {@link Templated}, {@link EventHandler}, {@link Bound}
*
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
* @author Christian Sadilek <csadilek@redhat.com>
* @author Jonathan Fuerth <jfuerth@redhat.com>
* @author Max Barkley <mbarkley@redhat.com>
*/
@Inherited
@Documented
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface DataField {
/**
* Represents the different strategies used to resolve conflicts between attribute values of the template HTML element
* and attributes of the {@link DataField}.
*/
public static enum ConflictStrategy {
/**
* <p>
* Uses attribute values from the {@link DataField} in the templated Java class when available. Under this strategy
* an attribute value from the template is only used if the {@link DataField} does not already have a value for the
* respective attribute.
*
* <p>
* <b>Exceptions:</b>
* <ul>
* <li>CSS class names from the template and the {@link DataField} are all kept regardless of
* {@link ConflictStrategy}.
* <li>CSS styles (declared in the {@code style} property) are merged together, and this strategy is only applied to
* conflicting property values (where the property value from the {@link DataField} in the templated Java class is used).
* </ul>
*/
USE_BEAN,
/**
* <p>
* Uses attribute values from the HTML template element when available. Under this strategy all attribute values
* from the template are used and values from the {@link DataField} are used if the templated HTML element does not
* already have a value for the respective attribute.
*
* <p>
* <b>Exceptions:</b>
* <ul>
* <li>CSS class names from the template and the {@link DataField} are all kept regardless of
* {@link ConflictStrategy}.
* <li>CSS styles (declared in the {@code style} property) are merged together, and this strategy is only applied to
* conflicting property values (where the property value from the template HTML element is used).
* </ul>
*/
USE_TEMPLATE
}
/**
* Holds a {@link ConflictStrategy} for a particular HTML element attribute.
*/
public static @interface AttributeRule {
/**
* The name of an HTML Element attribute.
*/
String name();
/**
* A {@link ConflictStrategy} used to merge values of the named HTML element attribute.
*/
ConflictStrategy strategy();
}
/**
* Specify the name of the <code>data-field</code> in the corresponding HTML template, which the annotated element
* represents.
*/
String value() default "";
/**
* Used to declare how values of attributes are merged from the HTML template element to this {@link DataField}.
*/
AttributeRule[] attributeRules() default {};
/**
* Declare a default strategy used to mergve attribute values from the HTML template element to this
* {@link DataField}. This strategy will be used for every attribute except ones overriden in {@link #attributeRules()}.
*/
ConflictStrategy defaultStrategy() default USE_TEMPLATE;
}