// Path: binder/src/main/java/com/artfulbits/binding/exceptions/WrongConfigurationError.java
// public class WrongConfigurationError extends ConfigurationError {
//   /* [ CONSTANTS ] ================================================================================================= */
// 
//   /** Serialization identifier. */
//   private static final long serialVersionUID = 498019655467980342L;
// 
// 	/* [ CONSTRUCTORS ] ============================================================================================== */
// 
//   public WrongConfigurationError(final String msg) {
//     super(msg);
//   }
// 
//   public WrongConfigurationError(final String msg, final Throwable inner) {
//     super(msg, inner);
//   }
// 
// 	/* [ GETTER / SETTER METHODS ] =================================================================================== */
// 
//   /** Create a long message from inner exceptions. */
//   @Override
//   public String getMessage() {
//     final StringBuilder sb = new StringBuilder();
//     final String separator = "\n";
// 
//     for (final Throwable t : getReasons()) {
//       sb.append(separator).append(t.getMessage());
//     }
// 
//     return super.getMessage() + sb.toString();
//   }
// }


import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.artfulbits.binding.exceptions.WrongConfigurationError;
import java.util.List;
import java.util.Locale;
package com.artfulbits.binding.reflection;




/** Class is responsible for accessing a specific abstract 'field' by using reflection. */
@SuppressWarnings("unused")
public class Property<T> {
  /* [ CONSTANTS ] ================================================================================================= */

  /** Use this constant for defining 'empty' name of the getter or setter. */
  public static final String NO_NAME = "";
  /** Array of possible prefixes used for getting the value. */
  private static final String[] KNOWN_GETTERS = new String[]{"get", "has", "is", "exceeds", "m", ""};
  /** Array of possible prefixes used for setting the value. */
  private static final String[] KNOWN_SETTERS = new String[]{"set", "m", ""};

	/* [ MEMBERS ] =================================================================================================== */

  /** Property data type. */
  private final Class<T> mType;
  /** Property name pattern. */
  private final String mName;
  /** reference on reflected class entry used for GET operation. */
  private Entry mResolvedGet;
  /** reference on reflected class entry used for SET operation. */
  private Entry mResolvedSet;
  /** Name of found 'get' entry. */
  private String mStrictGet;
  /** Name of found 'set' entry. */
  private String mStrictSet;

	/* [ CONSTRUCTORS ] ============================================================================================== */

  /** Expected automatic 'get' and 'set' finding. */
  public Property(@NonNull final Class<T> type, @NonNull final String name) {
    mType = type;
    mName = name;
  }

  /** 'get' and 'set' are explicitly defined. */
  public Property(@NonNull final Class<T> type, @NonNull final String getName, @NonNull final String setName) {
    mType = type;
    mName = null;

    mStrictGet = getName;
    mStrictSet = setName;
  }

  /**
   * Resolve property logic to human readable string.
   * <p/>
   * Example 1: .getText() | setText()<br/> Example 2: .findViewById(...) | &lt;none&gt;()<br/> Example 3: .{Text}(...)
   * | &lt;none&gt;()<br/>
   */
  @Override
  public String toString() {
    final boolean isPattern = (null != mName && !NO_NAME.equals(mName));
    final boolean isStrictGet = (null != mStrictGet && !NO_NAME.equals(mStrictGet));
    final boolean isStrictSet = (null != mStrictSet && !NO_NAME.equals(mStrictSet));

    final String search = isPattern ? "{" + mName + "}" : "<none>";
    final String getter = isStrictGet ? (null == mResolvedGet ? "{" + mStrictGet + "}" : mResolvedGet.toString()) : search;
    final String setter = isStrictSet ? (null == mResolvedSet ? "{" + mStrictSet + "}" : mResolvedSet.toString()) : search;

    return String.format(Locale.US, "%s | %s", getter, setter);
  }

  @NonNull
  public String toGetterString() {
    final boolean isPattern = (null != mName && !NO_NAME.equals(mName));
    final boolean isGet = (null != mStrictGet && !NO_NAME.equals(mStrictGet));
    final String search = isPattern ? "{" + mName + "}" : "<none>";

    return isGet ? (null == mResolvedGet) ? "{" + mStrictGet + "}" : mResolvedGet.toString() : search;
  }

  @NonNull
  public String toSetterString() {
    final boolean isPattern = (null != mName && !NO_NAME.equals(mName));
    final boolean isSet = (null != mStrictSet && !NO_NAME.equals(mStrictSet));
    final String search = isPattern ? "{" + mName + "}" : "<none>";

    return isSet ? (null == mResolvedSet) ? "{" + mStrictSet + "}" : mResolvedSet.toString() : search;
  }

	/* [ GETTER / SETTER METHODS ] =================================================================================== */

  /** Get property data type. */
  @NonNull
  public final Class<T> getDataType() {
    return mType;
  }

  /** Get resolved 'get' entry name. Null - if not resolved yet. */
  @Nullable
  public String getGetterName() {
    return mStrictGet;
  }

  /** Get resolved 'set' entry name. Null - if not resolved yet. */
  @Nullable
  public String getSetterName() {
    return mStrictSet;
  }

  /** Get property value. */
  public T get(@NonNull final Object instance) {
    return get(instance, getterArguments());
  }

  @SuppressWarnings("unchecked")
  public T get(@NonNull final Object instance, final Object... args) {
    try {
      if (null == mResolvedGet) {
        mResolvedGet = extractGetter(instance);
      }

      if (null == mResolvedGet) {
// Path: binder/src/main/java/com/artfulbits/binding/exceptions/WrongConfigurationError.java
// public class WrongConfigurationError extends ConfigurationError {
//   /* [ CONSTANTS ] ================================================================================================= */
// 
//   /** Serialization identifier. */
//   private static final long serialVersionUID = 498019655467980342L;
// 
// 	/* [ CONSTRUCTORS ] ============================================================================================== */
// 
//   public WrongConfigurationError(final String msg) {
//     super(msg);
//   }
// 
//   public WrongConfigurationError(final String msg, final Throwable inner) {
//     super(msg, inner);
//   }
// 
// 	/* [ GETTER / SETTER METHODS ] =================================================================================== */
// 
//   /** Create a long message from inner exceptions. */
//   @Override
//   public String getMessage() {
//     final StringBuilder sb = new StringBuilder();
//     final String separator = "\n";
// 
//     for (final Throwable t : getReasons()) {
//       sb.append(separator).append(t.getMessage());
//     }
// 
//     return super.getMessage() + sb.toString();
//   }
// }


// Path: binder/src/main/java/com/artfulbits/binding/reflection/Property.java
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.artfulbits.binding.exceptions.WrongConfigurationError;
import java.util.List;
import java.util.Locale;

package com.artfulbits.binding.reflection;




/** Class is responsible for accessing a specific abstract 'field' by using reflection. */
@SuppressWarnings("unused")
public class Property<T> {
  /* [ CONSTANTS ] ================================================================================================= */

  /** Use this constant for defining 'empty' name of the getter or setter. */
  public static final String NO_NAME = "";
  /** Array of possible prefixes used for getting the value. */
  private static final String[] KNOWN_GETTERS = new String[]{"get", "has", "is", "exceeds", "m", ""};
  /** Array of possible prefixes used for setting the value. */
  private static final String[] KNOWN_SETTERS = new String[]{"set", "m", ""};

	/* [ MEMBERS ] =================================================================================================== */

  /** Property data type. */
  private final Class<T> mType;
  /** Property name pattern. */
  private final String mName;
  /** reference on reflected class entry used for GET operation. */
  private Entry mResolvedGet;
  /** reference on reflected class entry used for SET operation. */
  private Entry mResolvedSet;
  /** Name of found 'get' entry. */
  private String mStrictGet;
  /** Name of found 'set' entry. */
  private String mStrictSet;

	/* [ CONSTRUCTORS ] ============================================================================================== */

  /** Expected automatic 'get' and 'set' finding. */
  public Property(@NonNull final Class<T> type, @NonNull final String name) {
    mType = type;
    mName = name;
  }

  /** 'get' and 'set' are explicitly defined. */
  public Property(@NonNull final Class<T> type, @NonNull final String getName, @NonNull final String setName) {
    mType = type;
    mName = null;

    mStrictGet = getName;
    mStrictSet = setName;
  }

  /**
   * Resolve property logic to human readable string.
   * <p/>
   * Example 1: .getText() | setText()<br/> Example 2: .findViewById(...) | &lt;none&gt;()<br/> Example 3: .{Text}(...)
   * | &lt;none&gt;()<br/>
   */
  @Override
  public String toString() {
    final boolean isPattern = (null != mName && !NO_NAME.equals(mName));
    final boolean isStrictGet = (null != mStrictGet && !NO_NAME.equals(mStrictGet));
    final boolean isStrictSet = (null != mStrictSet && !NO_NAME.equals(mStrictSet));

    final String search = isPattern ? "{" + mName + "}" : "<none>";
    final String getter = isStrictGet ? (null == mResolvedGet ? "{" + mStrictGet + "}" : mResolvedGet.toString()) : search;
    final String setter = isStrictSet ? (null == mResolvedSet ? "{" + mStrictSet + "}" : mResolvedSet.toString()) : search;

    return String.format(Locale.US, "%s | %s", getter, setter);
  }

  @NonNull
  public String toGetterString() {
    final boolean isPattern = (null != mName && !NO_NAME.equals(mName));
    final boolean isGet = (null != mStrictGet && !NO_NAME.equals(mStrictGet));
    final String search = isPattern ? "{" + mName + "}" : "<none>";

    return isGet ? (null == mResolvedGet) ? "{" + mStrictGet + "}" : mResolvedGet.toString() : search;
  }

  @NonNull
  public String toSetterString() {
    final boolean isPattern = (null != mName && !NO_NAME.equals(mName));
    final boolean isSet = (null != mStrictSet && !NO_NAME.equals(mStrictSet));
    final String search = isPattern ? "{" + mName + "}" : "<none>";

    return isSet ? (null == mResolvedSet) ? "{" + mStrictSet + "}" : mResolvedSet.toString() : search;
  }

	/* [ GETTER / SETTER METHODS ] =================================================================================== */

  /** Get property data type. */
  @NonNull
  public final Class<T> getDataType() {
    return mType;
  }

  /** Get resolved 'get' entry name. Null - if not resolved yet. */
  @Nullable
  public String getGetterName() {
    return mStrictGet;
  }

  /** Get resolved 'set' entry name. Null - if not resolved yet. */
  @Nullable
  public String getSetterName() {
    return mStrictSet;
  }

  /** Get property value. */
  public T get(@NonNull final Object instance) {
    return get(instance, getterArguments());
  }

  @SuppressWarnings("unchecked")
  public T get(@NonNull final Object instance, final Object... args) {
    try {
      if (null == mResolvedGet) {
        mResolvedGet = extractGetter(instance);
      }

      if (null == mResolvedGet) {
        throw new WrongConfigurationError("Cannot resolve GET to real method/field." +