/* * The MIT License (MIT) * * Copyright (c) 2016. Diorite (by Bartłomiej Mazur (aka GotoFinal)) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package org.diorite.commons.reflections; import javax.annotation.Nullable; import java.lang.invoke.MethodHandle; import java.lang.reflect.Type; /** * Class that connect {@link ReflectGetter} and {@link ReflectSetter}, * allowing to get and set values using one object. * * @param <E> * type of value. */ public class ReflectedProperty<E> implements ReflectGetter<E>, ReflectSetter<E> { @Nullable private final ReflectGetter<E> getter; @Nullable private final ReflectSetter<E> setter; /** * Construct new reflect element using given getter and setter instance. * * @param getter * getter for value. * @param setter * setter for value. */ public ReflectedProperty(@Nullable ReflectGetter<E> getter, @Nullable ReflectSetter<E> setter) { this.getter = getter; this.setter = setter; } ReflectedProperty(FieldAccessor<?> accessor) { ReflectField<E> reflectField = new ReflectField<>(accessor); this.getter = reflectField; this.setter = reflectField; } ReflectedProperty(MethodInvoker getter, MethodInvoker setter) { this.getter = new ReflectMethodGetter<>(getter); this.setter = new ReflectMethodSetter<>(setter); } ReflectedProperty(MethodInvoker getter, FieldAccessor<?> accessor) { this.getter = new ReflectMethodGetter<>(getter); this.setter = new ReflectField<>(accessor); } ReflectedProperty(FieldAccessor<?> accessor, MethodInvoker setter) { this.getter = new ReflectField<>(accessor); this.setter = new ReflectMethodSetter<>(setter); } @Override public E get(@Nullable Object src) { if (this.getter == null) { throw new IllegalStateException("Getter not provided."); } return this.getter.get(src); } @Nullable @Override public Object invokeWith(Object... args) throws IllegalArgumentException { if (this.isStatic()) { if (args.length == 0) { return this.get(null); } if (args.length == 1) { this.set(null, args[0]); return null; } throw new IllegalArgumentException("Expected none or single parameter."); } if (args.length == 1) { return this.get(args[0]); } if (args.length == 2) { this.set(args[0], args[1]); return null; } throw new IllegalArgumentException("Expected object instance and none or one parameter."); } @Override public String getName() { if (this.getter instanceof FieldAccessor) { return this.getter.getName(); } if (this.setter instanceof FieldAccessor) { return this.setter.getName(); } String baseName = null; if (this.getter != null) { baseName = this.getter.getName(); if (baseName.startsWith("get")) { char first = baseName.charAt(3); baseName.substring(4); return Character.toLowerCase(first) + baseName; } if (baseName.startsWith("is")) { char first = baseName.charAt(2); baseName.substring(3); return Character.toLowerCase(first) + baseName; } if (baseName.startsWith("has")) { char first = baseName.charAt(3); baseName.substring(4); return Character.toLowerCase(first) + baseName; } return baseName; } if (this.setter != null) { baseName = this.setter.getName(); if (baseName.startsWith("set")) { char first = baseName.charAt(3); baseName.substring(4); return Character.toLowerCase(first) + baseName; } return baseName; } throw new IllegalStateException("Both setter and getter is null."); } @Override public void set(@Nullable Object src, @Nullable Object obj) { if (this.setter == null) { throw new IllegalStateException("Setter not provided."); } this.setter.set(src, obj); } @Override public MethodHandle getSetter() { if (this.setter == null) { throw new IllegalStateException("Setter not provided."); } return this.setter.getSetter(); } @Override public MethodHandle getGetter() { if (this.getter == null) { throw new IllegalStateException("Getter not provided."); } return this.getter.getGetter(); } @Override public Type getGenericType() { if (this.getter == null) { throw new IllegalStateException("Missing getter instance"); } else { return this.getter.getGenericType(); } } @Override public int getModifiers() { if (this.getter != null) { return this.getter.getModifiers(); } if (this.setter != null) { return this.setter.getModifiers(); } throw new IllegalStateException("Missing getter/setter instance"); } @Override public void ensureAccessible() { if (this.getter != null) { this.getter.ensureAccessible(); } if (this.setter != null) { this.setter.ensureAccessible(); } } }