[77] | 1 | package com.framsticks.params; |
---|
| 2 | |
---|
| 3 | import java.lang.reflect.Field; |
---|
| 4 | import java.lang.reflect.InvocationTargetException; |
---|
[86] | 5 | import java.lang.reflect.Method; |
---|
[90] | 6 | import java.util.ArrayList; |
---|
[87] | 7 | import java.util.Collections; |
---|
[90] | 8 | import java.util.Comparator; |
---|
[86] | 9 | import java.util.HashMap; |
---|
[98] | 10 | import java.util.IdentityHashMap; |
---|
[88] | 11 | import java.util.List; |
---|
[86] | 12 | import java.util.Map; |
---|
[77] | 13 | |
---|
[87] | 14 | import javax.annotation.concurrent.Immutable; |
---|
| 15 | |
---|
[100] | 16 | import org.apache.logging.log4j.Logger; |
---|
| 17 | import org.apache.logging.log4j.LogManager; |
---|
[77] | 18 | |
---|
[87] | 19 | import com.framsticks.params.annotations.AutoAppendAnnotation; |
---|
[99] | 20 | import com.framsticks.params.types.EventParam; |
---|
[90] | 21 | import com.framsticks.params.types.ProcedureParam; |
---|
[86] | 22 | import com.framsticks.util.FramsticksException; |
---|
[87] | 23 | import com.framsticks.util.lang.Pair; |
---|
[77] | 24 | |
---|
[86] | 25 | import static com.framsticks.util.lang.Containers.*; |
---|
[84] | 26 | |
---|
[77] | 27 | /** |
---|
| 28 | * The Class ReflectionAccess. Stores data in provided object using reflection. |
---|
[84] | 29 | * |
---|
[77] | 30 | * @author Mateusz Jarus <name.surname@gmail.com> (please replace name and |
---|
| 31 | * surname with my personal data) |
---|
| 32 | * |
---|
| 33 | * @author Piotr Sniegowski |
---|
| 34 | */ |
---|
| 35 | public class ReflectionAccess extends SimpleAbstractAccess { |
---|
[100] | 36 | private final static Logger log = LogManager.getLogger(ReflectionAccess.class.getName()); |
---|
[77] | 37 | |
---|
[90] | 38 | protected final Class<?> javaClass; |
---|
[87] | 39 | protected final Backend backend; |
---|
| 40 | |
---|
[77] | 41 | private Object object; |
---|
| 42 | |
---|
[87] | 43 | @Immutable |
---|
| 44 | public static class Backend { |
---|
[86] | 45 | |
---|
[88] | 46 | protected static final Map<Pair<Class<?>, FramsClass>, Backend> synchronizedCache = Collections.synchronizedMap(new HashMap<Pair<Class<?>, FramsClass>, Backend>()); |
---|
[86] | 47 | |
---|
[90] | 48 | |
---|
| 49 | public interface ReflectedGetter { |
---|
| 50 | public <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException; |
---|
[87] | 51 | } |
---|
[86] | 52 | |
---|
[87] | 53 | public interface ReflectedSetter { |
---|
| 54 | public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException; |
---|
| 55 | } |
---|
| 56 | |
---|
[90] | 57 | public interface ReflectedCaller { |
---|
| 58 | public Object call(Object object, Object[] arguments) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException; |
---|
[87] | 59 | } |
---|
| 60 | |
---|
[99] | 61 | public interface ReflectedAdder{ |
---|
| 62 | public void reg(Object object, EventListener<?> listener) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException; |
---|
| 63 | } |
---|
| 64 | |
---|
| 65 | public interface ReflectedRemover{ |
---|
| 66 | public void regRemove(Object object, EventListener<?> listener) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException; |
---|
| 67 | } |
---|
| 68 | |
---|
[98] | 69 | protected final Map<ValueParam, ReflectedSetter> setters = new IdentityHashMap<>(); |
---|
| 70 | protected final Map<ValueParam, ReflectedGetter> getters = new IdentityHashMap<>(); |
---|
| 71 | protected final Map<ProcedureParam, ReflectedCaller> callers = new IdentityHashMap<>(); |
---|
[99] | 72 | protected final Map<EventParam, ReflectedAdder> adders = new IdentityHashMap<>(); |
---|
| 73 | protected final Map<EventParam, ReflectedRemover> removers = new IdentityHashMap<>(); |
---|
| 74 | |
---|
[90] | 75 | protected final List<Method> autoAppendMethods = new ArrayList<>(); |
---|
[87] | 76 | |
---|
| 77 | /** |
---|
| 78 | * @param params |
---|
| 79 | */ |
---|
[90] | 80 | public Backend() { |
---|
[87] | 81 | } |
---|
| 82 | |
---|
| 83 | public static Backend getOrCreateFor(Class<?> reflectedClass, FramsClass framsClass) { |
---|
| 84 | |
---|
| 85 | Pair<Class<?>, FramsClass> id = new Pair<Class<?>, FramsClass>(reflectedClass, framsClass); |
---|
| 86 | Backend backend = synchronizedCache.get(id); |
---|
| 87 | if (backend != null) { |
---|
| 88 | return backend; |
---|
| 89 | } |
---|
| 90 | |
---|
[100] | 91 | log.debug("constructing backend for {}", id); |
---|
[90] | 92 | backend = new Backend(); |
---|
[87] | 93 | |
---|
[90] | 94 | Map<String, ParamCandidate> candidates = ParamCandidate.getAllCandidates(reflectedClass).getCandidates(); |
---|
[87] | 95 | |
---|
| 96 | try { |
---|
[90] | 97 | for (final ProcedureParam pp : filterInstanceof(framsClass.getParamEntries(), ProcedureParam.class)) { |
---|
| 98 | if (!candidates.containsKey(pp.getId())) { |
---|
[100] | 99 | log.trace("java class does implement method {}", pp); |
---|
[90] | 100 | continue; |
---|
| 101 | } |
---|
| 102 | ParamCandidate pc = candidates.get(pp.getId()); |
---|
| 103 | final Method method = pc.getCaller(); |
---|
| 104 | |
---|
| 105 | backend.callers.put(pp, new ReflectedCaller() { |
---|
| 106 | |
---|
| 107 | @Override |
---|
| 108 | public Object call(Object object, Object[] arguments) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { |
---|
| 109 | return method.invoke(object, arguments); |
---|
| 110 | } |
---|
| 111 | }); |
---|
| 112 | |
---|
| 113 | } |
---|
| 114 | |
---|
[99] | 115 | for (final EventParam ep : filterInstanceof(framsClass.getParamEntries(), EventParam.class)) { |
---|
| 116 | if (!candidates.containsKey(ep.getId())) { |
---|
[100] | 117 | log.trace("java class does not implement the event param {}", ep); |
---|
[99] | 118 | continue; |
---|
| 119 | } |
---|
| 120 | ParamCandidate ec = candidates.get(ep.getId()); |
---|
| 121 | final Method adder = ec.getAdder(); |
---|
| 122 | final Method remover = ec.getRemover(); |
---|
| 123 | |
---|
| 124 | backend.adders.put(ep, new ReflectedAdder() { |
---|
| 125 | |
---|
| 126 | @Override |
---|
| 127 | public void reg(Object object, EventListener<?> listener) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { |
---|
| 128 | adder.invoke(object, listener); |
---|
| 129 | } |
---|
| 130 | }); |
---|
| 131 | |
---|
| 132 | backend.removers.put(ep, new ReflectedRemover() { |
---|
| 133 | |
---|
| 134 | @Override |
---|
| 135 | public void regRemove(Object object, EventListener<?> listener) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { |
---|
| 136 | remover.invoke(object, listener); |
---|
| 137 | } |
---|
| 138 | }); |
---|
| 139 | } |
---|
| 140 | |
---|
[87] | 141 | for (final ValueParam vp : filterInstanceof(framsClass.getParamEntries(), ValueParam.class)) { |
---|
| 142 | if (!candidates.containsKey(vp.getId())) { |
---|
| 143 | throw new ConstructionException().msg("missing candidate for param").arg("param", vp); |
---|
| 144 | } |
---|
| 145 | ParamCandidate pc = candidates.get(vp.getId()); |
---|
[99] | 146 | if (pc.isReadOnly() && !vp.hasFlag(ParamFlags.READONLY)) { |
---|
[87] | 147 | throw new ConstructionException().msg("readonly state conflict").arg("param", vp); |
---|
| 148 | } |
---|
| 149 | if (!typeMatch(pc.getRawType(), vp.getStorageType())) { |
---|
| 150 | throw new ConstructionException().msg("types mismatch for param").arg("param", vp).arg("candidate", pc.getType()).arg("storage", vp.getStorageType()); |
---|
| 151 | } |
---|
| 152 | |
---|
| 153 | final boolean primitive = pc.isPrimitive(); |
---|
| 154 | if (pc.getField() != null) { |
---|
| 155 | final Field f = pc.getField(); |
---|
[90] | 156 | backend.getters.put(vp, new ReflectedGetter() { |
---|
[87] | 157 | @Override |
---|
| 158 | public <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException { |
---|
| 159 | return type.cast(f.get(object)); |
---|
| 160 | } |
---|
[90] | 161 | }); |
---|
[87] | 162 | if (!pc.isFinal()) { |
---|
[90] | 163 | backend.setters.put(vp, new ReflectedSetter() { |
---|
[87] | 164 | @Override |
---|
| 165 | public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException { |
---|
| 166 | if (value == null && primitive) { |
---|
| 167 | throw new FramsticksException().msg("setting null to primitive value"); |
---|
| 168 | } |
---|
| 169 | f.set(object, value); |
---|
| 170 | } |
---|
[90] | 171 | }); |
---|
[87] | 172 | } |
---|
| 173 | } else { |
---|
| 174 | final Method g = pc.getGetter(); |
---|
| 175 | |
---|
[90] | 176 | backend.getters.put(vp, new ReflectedGetter() { |
---|
[87] | 177 | @Override |
---|
| 178 | public <T> T get(Object object, Class<T> type) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { |
---|
| 179 | return type.cast(g.invoke(object)); |
---|
| 180 | } |
---|
[90] | 181 | }); |
---|
[87] | 182 | |
---|
| 183 | if (!pc.isFinal()) { |
---|
| 184 | final Method s = pc.getSetter(); |
---|
[90] | 185 | backend.setters.put(vp, new ReflectedSetter() { |
---|
[87] | 186 | @Override |
---|
| 187 | public <T> void set(Object object, T value) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException { |
---|
| 188 | if (value == null && primitive) { |
---|
| 189 | throw new FramsticksException().msg("setting null to primitive value"); |
---|
| 190 | } |
---|
| 191 | s.invoke(object, value); |
---|
| 192 | } |
---|
[90] | 193 | }); |
---|
[87] | 194 | } |
---|
| 195 | } |
---|
| 196 | } |
---|
| 197 | } catch (ConstructionException e) { |
---|
| 198 | throw e.arg("java class", reflectedClass).arg("framsClass", framsClass); |
---|
| 199 | } |
---|
| 200 | |
---|
| 201 | Class<?> javaClass = reflectedClass; |
---|
| 202 | while (javaClass != null) { |
---|
| 203 | |
---|
| 204 | for (Method m : javaClass.getDeclaredMethods()) { |
---|
| 205 | AutoAppendAnnotation a = m.getAnnotation(AutoAppendAnnotation.class); |
---|
| 206 | if (a == null) { |
---|
| 207 | continue; |
---|
| 208 | } |
---|
| 209 | Class<?>[] args = m.getParameterTypes(); |
---|
| 210 | if (args.length != 1) { |
---|
| 211 | throw new ConstructionException().msg("invalid number of arguments in AutoAppend marked method").arg("method", m).arg("arguments", args.length); |
---|
| 212 | } |
---|
[90] | 213 | backend.autoAppendMethods.add(m); |
---|
[87] | 214 | } |
---|
| 215 | |
---|
| 216 | javaClass = javaClass.getSuperclass(); |
---|
| 217 | } |
---|
| 218 | |
---|
[90] | 219 | Collections.sort(backend.autoAppendMethods, new Comparator<Method>() { |
---|
| 220 | |
---|
| 221 | @Override |
---|
| 222 | public int compare(Method m0, Method m1) { |
---|
| 223 | Class<?> arg0 = m0.getParameterTypes()[0]; |
---|
| 224 | Class<?> arg1 = m1.getParameterTypes()[0]; |
---|
| 225 | if (arg0.isAssignableFrom(arg1)) { |
---|
| 226 | return 1; |
---|
| 227 | } |
---|
| 228 | if (arg1.isAssignableFrom(arg0)) { |
---|
| 229 | return -1; |
---|
| 230 | } |
---|
| 231 | return 0; |
---|
| 232 | } |
---|
| 233 | }); |
---|
| 234 | |
---|
[87] | 235 | synchronizedCache.put(id, backend); |
---|
| 236 | return backend; |
---|
| 237 | } |
---|
| 238 | |
---|
[86] | 239 | } |
---|
| 240 | |
---|
| 241 | public static boolean typeMatch(Class<?> a, Class<?> b) { |
---|
[99] | 242 | if (b.isPrimitive()) { |
---|
| 243 | throw new FramsticksException().msg("failed to match type, right argument is primitive").arg("left", a).arg("right", b); |
---|
| 244 | } |
---|
[86] | 245 | if (!a.isPrimitive()) { |
---|
| 246 | return a.equals(b); |
---|
| 247 | } |
---|
| 248 | |
---|
| 249 | if (a.equals(int.class)) { |
---|
| 250 | return b.equals(Integer.class); |
---|
| 251 | } |
---|
| 252 | if (a.equals(double.class)) { |
---|
| 253 | return b.equals(Double.class); |
---|
| 254 | } |
---|
| 255 | if (a.equals(boolean.class)) { |
---|
| 256 | return b.equals(Boolean.class); |
---|
| 257 | } |
---|
[99] | 258 | throw new FramsticksException().msg("failed to match types").arg("left", a).arg("right", b); |
---|
[86] | 259 | } |
---|
| 260 | |
---|
[99] | 261 | |
---|
| 262 | |
---|
| 263 | |
---|
| 264 | public ReflectionAccess(Class<?> javaClass) throws ConstructionException { |
---|
| 265 | this(javaClass, FramsClass.build().forClass(javaClass)); |
---|
| 266 | } |
---|
| 267 | |
---|
| 268 | |
---|
| 269 | public ReflectionAccess(Class<?> javaClass, FramsClass framsClass) throws ConstructionException { |
---|
| 270 | this(javaClass, framsClass, Backend.getOrCreateFor(javaClass, framsClass)); |
---|
| 271 | } |
---|
| 272 | |
---|
| 273 | protected ReflectionAccess(Class<?> javaClass, FramsClass framsClass, Backend backend) throws ConstructionException { |
---|
[87] | 274 | super(framsClass); |
---|
[99] | 275 | this.javaClass = javaClass; |
---|
| 276 | this.backend = backend; |
---|
[77] | 277 | } |
---|
| 278 | |
---|
[99] | 279 | @Override |
---|
| 280 | public ReflectionAccess cloneAccess() throws ConstructionException { |
---|
| 281 | return new ReflectionAccess(javaClass, framsClass, backend); |
---|
| 282 | } |
---|
[86] | 283 | |
---|
[77] | 284 | @Override |
---|
[84] | 285 | public <T> T get(ValueParam param, Class<T> type) { |
---|
[77] | 286 | try { |
---|
| 287 | try { |
---|
[86] | 288 | if (object == null) { |
---|
| 289 | throw new FramsticksException().msg("no object set"); |
---|
| 290 | } |
---|
| 291 | |
---|
[90] | 292 | return backend.getters.get(param).get(object, type); |
---|
[86] | 293 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { |
---|
| 294 | throw new FramsticksException().msg("failed to get").cause(e); |
---|
[77] | 295 | } |
---|
[86] | 296 | } catch (FramsticksException e) { |
---|
| 297 | throw e.arg("param", param).arg("type", type).arg("access", this); |
---|
[84] | 298 | } |
---|
[77] | 299 | } |
---|
| 300 | |
---|
| 301 | @Override |
---|
[84] | 302 | protected <T> void internalSet(ValueParam param, T value) { |
---|
[77] | 303 | setValue(param, value); |
---|
| 304 | } |
---|
| 305 | |
---|
[84] | 306 | private <T> void setValue(ValueParam param, T value) { |
---|
[77] | 307 | try { |
---|
| 308 | try { |
---|
[86] | 309 | if (object == null) { |
---|
| 310 | throw new FramsticksException().msg("no object set"); |
---|
[78] | 311 | } |
---|
[90] | 312 | Backend.ReflectedSetter s = backend.setters.get(param); |
---|
[86] | 313 | if (s == null) { |
---|
[90] | 314 | throw new FramsticksException().msg("trying to set unsettable"); |
---|
[100] | 315 | // return; |
---|
| 316 | // if (value != backend.getters.get(param).get(object, Object.class)) { |
---|
| 317 | // } |
---|
[78] | 318 | } |
---|
[86] | 319 | s.set(object, value); |
---|
| 320 | } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { |
---|
| 321 | throw new FramsticksException().msg("failed to set").cause(e); |
---|
[77] | 322 | } |
---|
[86] | 323 | } catch (FramsticksException e) { |
---|
| 324 | throw e.arg("param", param).arg("value", value).arg("access", this); |
---|
[77] | 325 | } |
---|
| 326 | } |
---|
| 327 | |
---|
[90] | 328 | @Override |
---|
[99] | 329 | public void reg(EventParam param, EventListener<?> listener) { |
---|
| 330 | try { |
---|
| 331 | try { |
---|
| 332 | if (object == null) { |
---|
| 333 | throw new FramsticksException().msg("no object set"); |
---|
| 334 | } |
---|
| 335 | |
---|
| 336 | backend.adders.get(param).reg(object, listener); |
---|
| 337 | return; |
---|
| 338 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { |
---|
| 339 | throw new FramsticksException().msg("failed to add listener").cause(e); |
---|
| 340 | } |
---|
| 341 | } catch (FramsticksException e) { |
---|
| 342 | throw e.arg("param", param).arg("access", this); |
---|
| 343 | } |
---|
| 344 | } |
---|
| 345 | |
---|
| 346 | @Override |
---|
| 347 | public void regRemove(EventParam param, EventListener<?> listener) { |
---|
| 348 | try { |
---|
| 349 | try { |
---|
| 350 | if (object == null) { |
---|
| 351 | throw new FramsticksException().msg("no object set"); |
---|
| 352 | } |
---|
| 353 | |
---|
| 354 | backend.removers.get(param).regRemove(object, listener); |
---|
| 355 | return; |
---|
| 356 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { |
---|
| 357 | throw new FramsticksException().msg("failed to remove listener").cause(e); |
---|
| 358 | } |
---|
| 359 | } catch (FramsticksException e) { |
---|
| 360 | throw e.arg("param", param).arg("access", this); |
---|
| 361 | } |
---|
| 362 | } |
---|
| 363 | |
---|
| 364 | @Override |
---|
[90] | 365 | public Object call(String id, Object[] arguments) { |
---|
| 366 | return call(framsClass.getParamEntry(id, ProcedureParam.class), arguments); |
---|
| 367 | } |
---|
| 368 | |
---|
| 369 | @Override |
---|
| 370 | public Object call(ProcedureParam param, Object[] arguments) { |
---|
| 371 | try { |
---|
| 372 | try { |
---|
| 373 | if (object == null) { |
---|
| 374 | throw new FramsticksException().msg("no object set"); |
---|
| 375 | } |
---|
| 376 | Backend.ReflectedCaller c = backend.callers.get(param); |
---|
| 377 | if (c == null) { |
---|
| 378 | throw new FramsticksException().msg("method is not bound"); |
---|
| 379 | } |
---|
| 380 | return c.call(object, arguments); |
---|
| 381 | } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { |
---|
| 382 | throw new FramsticksException().msg("failed to call").cause(e); |
---|
| 383 | } |
---|
| 384 | } catch (FramsticksException e) { |
---|
| 385 | throw e.arg("param", param).arg("access", this); |
---|
| 386 | } |
---|
| 387 | } |
---|
| 388 | |
---|
[77] | 389 | void resetErrors() { |
---|
| 390 | //TODO this replaces returnedObject.resetErrors(); |
---|
| 391 | } |
---|
| 392 | |
---|
| 393 | @Override |
---|
| 394 | public void clearValues() { |
---|
| 395 | if (object == null) { |
---|
| 396 | return; |
---|
| 397 | } |
---|
| 398 | |
---|
| 399 | resetErrors(); |
---|
| 400 | |
---|
| 401 | try { |
---|
[86] | 402 | for (ValueParam p : filterInstanceof(framsClass.getParamEntries(), ValueParam.class)) { |
---|
[78] | 403 | setValue(p, p.getDef(Object.class)); |
---|
[77] | 404 | } |
---|
[78] | 405 | } catch (IllegalArgumentException ex) { |
---|
[77] | 406 | ex.printStackTrace(); |
---|
| 407 | } |
---|
| 408 | } |
---|
| 409 | |
---|
| 410 | /** |
---|
| 411 | * Sets the new object to operate on. |
---|
[84] | 412 | * |
---|
[77] | 413 | * @param object |
---|
| 414 | * new object to operate on |
---|
| 415 | */ |
---|
| 416 | @Override |
---|
[84] | 417 | public ReflectionAccess select(Object object) { |
---|
[100] | 418 | this.object = Util.selectObjectForAccess(this, object, javaClass); |
---|
[84] | 419 | return this; |
---|
[77] | 420 | } |
---|
| 421 | |
---|
| 422 | @Override |
---|
| 423 | public Object getSelected() { |
---|
| 424 | return object; |
---|
| 425 | } |
---|
| 426 | |
---|
| 427 | // TODO: find a better place for it |
---|
| 428 | public static String objectToString(Object object) { |
---|
| 429 | StringBuilder b = new StringBuilder(); |
---|
| 430 | for (Field f : object.getClass().getFields()) { |
---|
| 431 | b.append(f.getName()); |
---|
| 432 | b.append(":"); |
---|
| 433 | try { |
---|
| 434 | Object value = f.get(object); |
---|
| 435 | b.append((value != null) ? value.toString() : "<null>"); |
---|
| 436 | } catch (IllegalAccessException e) { |
---|
| 437 | e.printStackTrace(); |
---|
| 438 | } |
---|
| 439 | b.append("\n"); |
---|
| 440 | } |
---|
| 441 | return b.toString(); |
---|
| 442 | } |
---|
| 443 | |
---|
| 444 | |
---|
[84] | 445 | @Override |
---|
| 446 | public Object createAccessee() { |
---|
| 447 | try { |
---|
[90] | 448 | return javaClass.newInstance(); |
---|
[85] | 449 | } catch (InstantiationException | IllegalAccessException e) { |
---|
[84] | 450 | e.printStackTrace(); |
---|
| 451 | } |
---|
[100] | 452 | log.fatal("failed to create reflected object of class {} for frams type {}", javaClass.getCanonicalName(), framsClass.getId()); |
---|
[84] | 453 | return null; |
---|
| 454 | } |
---|
[86] | 455 | |
---|
| 456 | |
---|
[87] | 457 | @Override |
---|
[96] | 458 | public void tryAutoAppend(Object value) { |
---|
[87] | 459 | assert object != null; |
---|
[96] | 460 | try { |
---|
| 461 | for (Method m : backend.autoAppendMethods) { |
---|
| 462 | if (m.getParameterTypes()[0].isAssignableFrom(value.getClass())) { |
---|
| 463 | try { |
---|
[100] | 464 | log.trace("auto appending with value {} with method {}", value, m); |
---|
[96] | 465 | m.invoke(object, value); |
---|
| 466 | return; |
---|
| 467 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | FramsticksException e) { |
---|
| 468 | throw new FramsticksException().msg("failed to auto append").cause(e).arg("with method", m); |
---|
| 469 | } |
---|
[87] | 470 | } |
---|
| 471 | } |
---|
[96] | 472 | throw new FramsticksException().msg("no method found to append"); |
---|
| 473 | } catch (FramsticksException e) { |
---|
| 474 | throw e.arg("value", value).arg("into object", object); |
---|
[87] | 475 | } |
---|
[96] | 476 | |
---|
[87] | 477 | } |
---|
[90] | 478 | |
---|
[100] | 479 | @Override |
---|
| 480 | public String toString() { |
---|
| 481 | StringBuilder b = new StringBuilder(); |
---|
| 482 | b.append(framsClass); |
---|
| 483 | if (getSelected() != null) { |
---|
| 484 | b.append("(").append(getSelected()).append(")"); |
---|
| 485 | } |
---|
| 486 | return b.toString(); |
---|
| 487 | } |
---|
[77] | 488 | } |
---|
[86] | 489 | |
---|