001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau;
014
015import java.lang.reflect.*;
016
017import org.apache.juneau.reflect.*;
018
019/**
020 * Represents a simple settable value.
021 *
022 * <p>
023 * This object is not thread safe.
024 *
025 * @param <T> The value type.
026 */
027public class Value<T> {
028
029   /**
030    * Returns the generic parameter type of the Value parameter at the specified position.
031    *
032    * <h5 class='figure'>Example:</h5>
033    * <p class='bcode w800'>
034    *    <jk>public class</jk> A {
035    *       <jk>public void</jk> doX(Value&lt;Foo&gt; foo) {...}
036    *    }
037    * </p>
038    * <p class='bcode w800'>
039    *    Class&lt;?&gt; t = Value.<jsm>getValueType</jsm>(A.<jk>class</jk>.getMethod(<js>"doX"</js>, Value.<jk>class</jk>));
040    *    <jsm>assertTrue</jsm>(t == Foo.<jk>class</jk>);
041    * </p>
042    *
043    * @param m The method containing the parameter.
044    * @param i The index of the parameter.
045    * @return The parameter type of the value, or <jk>null</jk> if the method parameter is not of type <c>Value</c>.
046    */
047   public static Type getParameterType(Method m, int i) {
048      return getParameterType(m.getGenericParameterTypes()[i]);
049   }
050
051   /**
052    * Returns the generic parameter type of the Value type.
053    *
054    * @param t The type to find the parameter type of.
055    * @return The parameter type of the value, or <jk>null</jk> if the type is not a subclass of <c>Value</c>.
056    */
057   public static Type getParameterType(Type t) {
058      if (t instanceof ParameterizedType) {
059         ParameterizedType pt = (ParameterizedType)t;
060         if (pt.getRawType() == Value.class) {
061            Type[] ta = pt.getActualTypeArguments();
062            if (ta.length > 0)
063               return ta[0];
064         }
065      } else if (t instanceof Class) {
066         Class<?> c = (Class<?>)t;
067         if (Value.class.isAssignableFrom(c)) {
068            return ClassInfo.of(c).getParameterType(0, Value.class);
069         }
070      }
071
072      return null;
073   }
074
075   /**
076    * Convenience method for checking if the specified type is this class.
077    *
078    * @param t The type to check.
079    * @return <jk>true</jk> if the specified type is this class.
080    */
081   public static boolean isType(Type t) {
082      return
083         (t instanceof ParameterizedType && ((ParameterizedType)t).getRawType() == Value.class)
084         || (t instanceof Class && Value.class.isAssignableFrom((Class<?>)t));
085   }
086
087   private T t;
088   private ValueListener<T> listener;
089
090   /**
091    * Constructor.
092    */
093   public Value() {
094   }
095
096   /**
097    * Constructor.
098    *
099    * @param t Initial value.
100    */
101   public Value(T t) {
102      set(t);
103   }
104
105   /**
106    * Adds a listener for this value.
107    *
108    * @param listener The new listener for this value.
109    * @return This object (for method chaining).
110    */
111   public Value<T> listener(ValueListener<T> listener) {
112      this.listener = listener;
113      return this;
114   }
115
116   /**
117    * Sets the value.
118    *
119    * @param t The new value.
120    * @return This object (for method chaining).
121    */
122   public Value<T> set(T t) {
123      this.t = t;
124      if (listener != null)
125         listener.onSet(t);
126      return this;
127   }
128
129   /**
130    * Returns the value.
131    *
132    * @return The value, or <jk>null</jk> if it is not set.
133    */
134   public T get() {
135      return t;
136   }
137
138   /**
139    * Returns <jk>true</jk> if the value is set.
140    *
141    * @return <jk>true</jk> if the value is set.
142    */
143   public boolean isSet() {
144      return get() != null;
145   }
146}