Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 candr.yoclip.option; import java.lang.reflect.Field; import java.util.Collections; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import candr.yoclip.OptionsParseException; import candr.yoclip.ParserOption; /** * Used by the parser to associate an {@link candr.yoclip.annotation.Option Option} or * {@link candr.yoclip.annotation.OptionProperties OptionProperties} annotation with a {@code Field} in a class that * contains option parser annotations. */ abstract class AbstractFieldOption<T> implements ParserOption<T> { /** * The field that has an options annotation associated with it. */ private Field field; /** * Initializes the field descriptor to create an association between the bean {@code Field} and the {@code Option} * annotation. * * @param field The bean field annotated with {@code Option}. */ protected AbstractFieldOption(final Field field) { this.field = field; } /** * Get the Java {@code Field} that is annotated with either {@link candr.yoclip.annotation.Option Option} or * {@link candr.yoclip.annotation.OptionProperties}. * * @return the Java {@code Field} that has an option annotation associated with it. */ public Field getField() { return field; } /** * Get the {@code Class} object that identifies the declared type for the {@code Field} object. * * @return the {@code Class} that identifies the declared type for the {@code Field}. */ public Class<?> getType() { return getField().getType(); } /** * The {@code Class} object representing the class or interface that declares the {@code Field}. * * @return the {@code Class} that declares the {@code Field}. */ @Override public Class<?> getDeclaringClass() { return getField().getDeclaringClass(); } /** * The default unique id for a {@code Field} is the name of the field. * * @return the name of the field. */ @Override public String getUniqueId() { return getField().getName(); } /** * Used to flag the option as requesting help. * * @return {@code true} if the option is help related, {@code false} otherwise. */ @Override public boolean isHelp() { return false; } /** * Indicates the field is annotated with a {@link candr.yoclip.annotation.OptionProperties OptionProperties} annotation. * * @return {@code true} if the annotation is {@code OptionProperties}, {@code false} otherwise. */ @Override public boolean isProperties() { return false; } /** * Indicates the field is annotated with a {@link candr.yoclip.annotation.Arguments Arguments} annotation. * * @return {@code true} if the annotation is {@code Arguments}, {@code false} otherwise. */ @Override public boolean isArguments() { return false; } /** * Indicates when an option is used a value must also be included. * * @return {@code true} is a value is required, {@code false} otherwise. */ @Override public boolean hasValue() { return false; } @Override public List<Pair<String, String>> getPropertyDescriptions() { return Collections.emptyList(); } protected void set(final T bean, final Value<T> value) { final Field field = getField(); boolean resetFieldAccessibility = false; try { if (!field.isAccessible()) { field.setAccessible(true); resetFieldAccessibility = true; } value.set(bean, field); } catch (Exception e) { if (e instanceof OptionsParseException) { throw (OptionsParseException) e; } throw new OptionsParseException("Error setting field " + getUniqueId(), e); } finally { if (resetFieldAccessibility) { field.setAccessible(false); } } } @Override public String toString() { return getUniqueId(); } /** * Used internally to set a field value. Callers use the interface similar to a poor mans closure. The setters * framework ensures a normally inaccessible field is settable before calling the {@link Value#set set} method. * * @param <T> The bean type that will be updated. */ public interface Value<T> { /** * Called by the framework when a value should be set into a field of a bean object. * * @param bean The object whose field will be set. * @param field The field in the object that will be set. * @throws IllegalAccessException This can be called if the field has been marked final. */ void set(T bean, Field field) throws IllegalAccessException; } }