You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MethodProperty.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.v7.data.util;
  17. import static com.vaadin.util.ReflectTools.convertPrimitiveType;
  18. import java.io.IOException;
  19. import java.lang.reflect.InvocationTargetException;
  20. import java.lang.reflect.Method;
  21. import java.util.Arrays;
  22. import java.util.logging.Level;
  23. import java.util.logging.Logger;
  24. import com.vaadin.shared.util.SharedUtil;
  25. import com.vaadin.v7.data.Property;
  26. import com.vaadin.v7.util.SerializerHelper;
  27. /**
  28. * <p>
  29. * Proxy class for creating Properties from pairs of getter and setter methods
  30. * of a Bean property. An instance of this class can be thought as having been
  31. * attached to a field of an object. Accessing the object through the Property
  32. * interface directly manipulates the underlying field.
  33. * </p>
  34. *
  35. * <p>
  36. * It's assumed that the return value returned by the getter method is
  37. * assignable to the type of the property, and the setter method parameter is
  38. * assignable to that value.
  39. * </p>
  40. *
  41. * <p>
  42. * A valid getter method must always be available, but instance of this class
  43. * can be constructed with a <code>null</code> setter method in which case the
  44. * resulting MethodProperty is read-only.
  45. * </p>
  46. *
  47. * <p>
  48. * MethodProperty implements Property.ValueChangeNotifier, but does not
  49. * automatically know whether or not the getter method will actually return a
  50. * new value - value change listeners are always notified when setValue is
  51. * called, without verifying what the getter returns.
  52. * </p>
  53. *
  54. * @author Vaadin Ltd.
  55. * @since 3.0
  56. */
  57. @Deprecated
  58. @SuppressWarnings("serial")
  59. public class MethodProperty<T> extends AbstractProperty<T> {
  60. /**
  61. * The object that includes the property the MethodProperty is bound to.
  62. */
  63. private transient Object instance;
  64. /**
  65. * Argument arrays for the getter and setter methods.
  66. */
  67. private transient Object[] setArgs, getArgs;
  68. /**
  69. * The getter and setter methods.
  70. */
  71. private transient Method setMethod, getMethod;
  72. /**
  73. * Index of the new value in the argument list for the setter method. If the
  74. * setter method requires several parameters, this index tells which one is
  75. * the actual value to change.
  76. */
  77. private int setArgumentIndex;
  78. /**
  79. * Type of the property.
  80. */
  81. private transient Class<? extends T> type;
  82. private static final Object[] DEFAULT_GET_ARGS = new Object[0];
  83. private static final Object[] DEFAULT_SET_ARGS = new Object[1];
  84. /* Special serialization to handle method references */
  85. private void writeObject(java.io.ObjectOutputStream out)
  86. throws IOException {
  87. out.defaultWriteObject();
  88. SerializerHelper.writeClass(out, type);
  89. out.writeObject(instance);
  90. out.writeObject(setArgs);
  91. out.writeObject(getArgs);
  92. if (setMethod != null) {
  93. out.writeObject(setMethod.getName());
  94. SerializerHelper.writeClassArray(out,
  95. setMethod.getParameterTypes());
  96. } else {
  97. out.writeObject(null);
  98. out.writeObject(null);
  99. }
  100. if (getMethod != null) {
  101. out.writeObject(getMethod.getName());
  102. SerializerHelper.writeClassArray(out,
  103. getMethod.getParameterTypes());
  104. } else {
  105. out.writeObject(null);
  106. out.writeObject(null);
  107. }
  108. }
  109. /* Special serialization to handle method references */
  110. private void readObject(java.io.ObjectInputStream in)
  111. throws IOException, ClassNotFoundException {
  112. in.defaultReadObject();
  113. try {
  114. @SuppressWarnings("unchecked")
  115. // business assumption; type parameters not checked at runtime
  116. Class<T> class1 = (Class<T>) SerializerHelper.readClass(in);
  117. type = class1;
  118. instance = in.readObject();
  119. Object[] setArgs = (Object[]) in.readObject();
  120. Object[] getArgs = (Object[]) in.readObject();
  121. setArguments(getArgs, setArgs, setArgumentIndex);
  122. String name = (String) in.readObject();
  123. Class<?>[] paramTypes = SerializerHelper.readClassArray(in);
  124. if (instance != null && name != null) {
  125. setMethod = instance.getClass().getMethod(name, paramTypes);
  126. } else {
  127. setMethod = null;
  128. }
  129. name = (String) in.readObject();
  130. paramTypes = SerializerHelper.readClassArray(in);
  131. if (instance != null && name != null) {
  132. getMethod = instance.getClass().getMethod(name, paramTypes);
  133. } else {
  134. getMethod = null;
  135. }
  136. } catch (SecurityException e) {
  137. getLogger().log(Level.SEVERE, "Internal deserialization error", e);
  138. } catch (NoSuchMethodException e) {
  139. getLogger().log(Level.SEVERE, "Internal deserialization error", e);
  140. }
  141. }
  142. /**
  143. * <p>
  144. * Creates a new instance of <code>MethodProperty</code> from a named bean
  145. * property. This constructor takes an object and the name of a bean
  146. * property and initializes itself with the accessor methods for the
  147. * property.
  148. * </p>
  149. * <p>
  150. * The getter method of a <code>MethodProperty</code> instantiated with this
  151. * constructor will be called with no arguments, and the setter method with
  152. * only the new value as the sole argument.
  153. * </p>
  154. *
  155. * <p>
  156. * If the setter method is unavailable, the resulting
  157. * <code>MethodProperty</code> will be read-only, otherwise it will be
  158. * read-write.
  159. * </p>
  160. *
  161. * <p>
  162. * Method names are constructed from the bean property by adding
  163. * get/is/are/set prefix and capitalising the first character in the name of
  164. * the given bean property.
  165. * </p>
  166. *
  167. * @param instance
  168. * the object that includes the property.
  169. * @param beanPropertyName
  170. * the name of the property to bind to.
  171. */
  172. @SuppressWarnings("unchecked")
  173. public MethodProperty(Object instance, String beanPropertyName) {
  174. final Class<?> beanClass = instance.getClass();
  175. // Assure that the first letter is upper cased (it is a common
  176. // mistake to write firstName, not FirstName).
  177. beanPropertyName = SharedUtil.capitalize(beanPropertyName);
  178. // Find the get method
  179. getMethod = null;
  180. try {
  181. getMethod = initGetterMethod(beanPropertyName, beanClass);
  182. } catch (final java.lang.NoSuchMethodException ignored) {
  183. throw new MethodException(this,
  184. "Bean property " + beanPropertyName + " can not be found");
  185. }
  186. // In case the get method is found, resolve the type
  187. Class<?> returnType = getMethod.getReturnType();
  188. // Finds the set method
  189. setMethod = null;
  190. try {
  191. setMethod = beanClass.getMethod("set" + beanPropertyName,
  192. new Class[] { returnType });
  193. } catch (final java.lang.NoSuchMethodException skipped) {
  194. }
  195. // Gets the return type from get method
  196. if (returnType.isPrimitive()) {
  197. type = (Class<T>) convertPrimitiveType(returnType);
  198. if (type.isPrimitive()) {
  199. throw new MethodException(this,
  200. "Bean property " + beanPropertyName
  201. + " getter return type must not be void");
  202. }
  203. } else {
  204. type = (Class<T>) returnType;
  205. }
  206. setArguments(DEFAULT_GET_ARGS, DEFAULT_SET_ARGS, 0);
  207. this.instance = instance;
  208. }
  209. /**
  210. * <p>
  211. * Creates a new instance of <code>MethodProperty</code> from named getter
  212. * and setter methods. The getter method of a <code>MethodProperty</code>
  213. * instantiated with this constructor will be called with no arguments, and
  214. * the setter method with only the new value as the sole argument.
  215. * </p>
  216. *
  217. * <p>
  218. * If the setter method is <code>null</code>, the resulting
  219. * <code>MethodProperty</code> will be read-only, otherwise it will be
  220. * read-write.
  221. * </p>
  222. *
  223. * @param type
  224. * the type of the property.
  225. * @param instance
  226. * the object that includes the property.
  227. * @param getMethodName
  228. * the name of the getter method.
  229. * @param setMethodName
  230. * the name of the setter method.
  231. *
  232. */
  233. public MethodProperty(Class<? extends T> type, Object instance,
  234. String getMethodName, String setMethodName) {
  235. this(type, instance, getMethodName, setMethodName, new Object[] {},
  236. new Object[] { null }, 0);
  237. }
  238. /**
  239. * <p>
  240. * Creates a new instance of <code>MethodProperty</code> with the getter and
  241. * setter methods. The getter method of a <code>MethodProperty</code>
  242. * instantiated with this constructor will be called with no arguments, and
  243. * the setter method with only the new value as the sole argument.
  244. * </p>
  245. *
  246. * <p>
  247. * If the setter method is <code>null</code>, the resulting
  248. * <code>MethodProperty</code> will be read-only, otherwise it will be
  249. * read-write.
  250. * </p>
  251. *
  252. * @param type
  253. * the type of the property.
  254. * @param instance
  255. * the object that includes the property.
  256. * @param getMethod
  257. * the getter method.
  258. * @param setMethod
  259. * the setter method.
  260. */
  261. public MethodProperty(Class<? extends T> type, Object instance,
  262. Method getMethod, Method setMethod) {
  263. this(type, instance, getMethod, setMethod, new Object[] {},
  264. new Object[] { null }, 0);
  265. }
  266. /**
  267. * <p>
  268. * Creates a new instance of <code>MethodProperty</code> from named getter
  269. * and setter methods and argument lists. The getter method of a
  270. * <code>MethodProperty</code> instantiated with this constructor will be
  271. * called with the getArgs as arguments. The setArgs will be used as the
  272. * arguments for the setter method, though the argument indexed by the
  273. * setArgumentIndex will be replaced with the argument passed to the
  274. * {@link #setValue(Object newValue)} method.
  275. * </p>
  276. *
  277. * <p>
  278. * For example, if the <code>setArgs</code> contains <code>A</code>,
  279. * <code>B</code> and <code>C</code>, and <code>setArgumentIndex =
  280. * 1</code>, the call <code>methodProperty.setValue(X)</code> would result
  281. * in the setter method to be called with the parameter set of
  282. * <code>{A, X, C}</code>
  283. * </p>
  284. *
  285. * @param type
  286. * the type of the property.
  287. * @param instance
  288. * the object that includes the property.
  289. * @param getMethodName
  290. * the name of the getter method.
  291. * @param setMethodName
  292. * the name of the setter method.
  293. * @param getArgs
  294. * the fixed argument list to be passed to the getter method.
  295. * @param setArgs
  296. * the fixed argument list to be passed to the setter method.
  297. * @param setArgumentIndex
  298. * the index of the argument in <code>setArgs</code> to be
  299. * replaced with <code>newValue</code> when
  300. * {@link #setValue(Object newValue)} is called.
  301. */
  302. @SuppressWarnings("unchecked")
  303. public MethodProperty(Class<? extends T> type, Object instance,
  304. String getMethodName, String setMethodName, Object[] getArgs,
  305. Object[] setArgs, int setArgumentIndex) {
  306. // Check the setargs and setargs index
  307. if (setMethodName != null && setArgs == null) {
  308. throw new IndexOutOfBoundsException("The setArgs can not be null");
  309. }
  310. if (setMethodName != null && (setArgumentIndex < 0
  311. || setArgumentIndex >= setArgs.length)) {
  312. throw new IndexOutOfBoundsException(
  313. "The setArgumentIndex must be >= 0 and < setArgs.length");
  314. }
  315. // Set type
  316. this.type = type;
  317. // Find set and get -methods
  318. final Method[] m = instance.getClass().getMethods();
  319. // Finds get method
  320. boolean found = false;
  321. for (int i = 0; i < m.length; i++) {
  322. // Tests the name of the get Method
  323. if (!m[i].getName().equals(getMethodName)) {
  324. // name does not match, try next method
  325. continue;
  326. }
  327. // Tests return type
  328. if (!type.equals(m[i].getReturnType())) {
  329. continue;
  330. }
  331. // Tests the parameter types
  332. final Class<?>[] c = m[i].getParameterTypes();
  333. if (c.length != getArgs.length) {
  334. // not the right amount of parameters, try next method
  335. continue;
  336. }
  337. int j = 0;
  338. while (j < c.length) {
  339. if (getArgs[j] != null
  340. && !c[j].isAssignableFrom(getArgs[j].getClass())) {
  341. // parameter type does not match, try next method
  342. break;
  343. }
  344. j++;
  345. }
  346. if (j == c.length) {
  347. // all paramteters matched
  348. if (found == true) {
  349. throw new MethodException(this,
  350. "Could not uniquely identify " + getMethodName
  351. + "-method");
  352. } else {
  353. found = true;
  354. getMethod = m[i];
  355. }
  356. }
  357. }
  358. if (found != true) {
  359. throw new MethodException(this,
  360. "Could not find " + getMethodName + "-method");
  361. }
  362. // Finds set method
  363. if (setMethodName != null) {
  364. // Finds setMethod
  365. found = false;
  366. for (int i = 0; i < m.length; i++) {
  367. // Checks name
  368. if (!m[i].getName().equals(setMethodName)) {
  369. // name does not match, try next method
  370. continue;
  371. }
  372. // Checks parameter compatibility
  373. final Class<?>[] c = m[i].getParameterTypes();
  374. if (c.length != setArgs.length) {
  375. // not the right amount of parameters, try next method
  376. continue;
  377. }
  378. int j = 0;
  379. while (j < c.length) {
  380. if (setArgs[j] != null
  381. && !c[j].isAssignableFrom(setArgs[j].getClass())) {
  382. // parameter type does not match, try next method
  383. break;
  384. } else if (j == setArgumentIndex && !c[j].equals(type)) {
  385. // Property type is not the same as setArg type
  386. break;
  387. }
  388. j++;
  389. }
  390. if (j == c.length) {
  391. // all parameters match
  392. if (found == true) {
  393. throw new MethodException(this,
  394. "Could not identify unique " + setMethodName
  395. + "-method");
  396. } else {
  397. found = true;
  398. setMethod = m[i];
  399. }
  400. }
  401. }
  402. if (found != true) {
  403. throw new MethodException(this,
  404. "Could not identify " + setMethodName + "-method");
  405. }
  406. }
  407. // Gets the return type from get method
  408. this.type = (Class<T>) convertPrimitiveType(type);
  409. setArguments(getArgs, setArgs, setArgumentIndex);
  410. this.instance = instance;
  411. }
  412. /**
  413. * <p>
  414. * Creates a new instance of <code>MethodProperty</code> from the getter and
  415. * setter methods, and argument lists.
  416. * </p>
  417. * <p>
  418. * This constructor behaves exactly like
  419. * {@link #MethodProperty(Class type, Object instance, String getMethodName, String setMethodName, Object [] getArgs, Object [] setArgs, int setArgumentIndex)}
  420. * except that instead of names of the getter and setter methods this
  421. * constructor is given the actual methods themselves.
  422. * </p>
  423. *
  424. * @param type
  425. * the type of the property.
  426. * @param instance
  427. * the object that includes the property.
  428. * @param getMethod
  429. * the getter method.
  430. * @param setMethod
  431. * the setter method.
  432. * @param getArgs
  433. * the fixed argument list to be passed to the getter method.
  434. * @param setArgs
  435. * the fixed argument list to be passed to the setter method.
  436. * @param setArgumentIndex
  437. * the index of the argument in <code>setArgs</code> to be
  438. * replaced with <code>newValue</code> when
  439. * {@link #setValue(Object newValue)} is called.
  440. */
  441. @SuppressWarnings("unchecked")
  442. // cannot use "Class<? extends T>" because of automatic primitive type
  443. // conversions
  444. public MethodProperty(Class<?> type, Object instance, Method getMethod,
  445. Method setMethod, Object[] getArgs, Object[] setArgs,
  446. int setArgumentIndex) {
  447. if (getMethod == null) {
  448. throw new MethodException(this,
  449. "Property GET-method cannot not be null: " + type);
  450. }
  451. if (setMethod != null) {
  452. if (setArgs == null) {
  453. throw new IndexOutOfBoundsException(
  454. "The setArgs can not be null");
  455. }
  456. if (setArgumentIndex < 0 || setArgumentIndex >= setArgs.length) {
  457. throw new IndexOutOfBoundsException(
  458. "The setArgumentIndex must be >= 0 and < setArgs.length");
  459. }
  460. }
  461. // Gets the return type from get method
  462. Class<? extends T> convertedType = (Class<? extends T>) convertPrimitiveType(
  463. type);
  464. this.getMethod = getMethod;
  465. this.setMethod = setMethod;
  466. setArguments(getArgs, setArgs, setArgumentIndex);
  467. this.instance = instance;
  468. this.type = convertedType;
  469. }
  470. /**
  471. * Find a getter method for a property (getXyz(), isXyz() or areXyz()).
  472. *
  473. * @param propertyName
  474. * name of the property
  475. * @param beanClass
  476. * class in which to look for the getter methods
  477. * @return Method
  478. * @throws NoSuchMethodException
  479. * if no getter found
  480. */
  481. static Method initGetterMethod(String propertyName,
  482. final Class<?> beanClass) throws NoSuchMethodException {
  483. propertyName = SharedUtil.capitalize(propertyName);
  484. Method getMethod = null;
  485. try {
  486. getMethod = beanClass.getMethod("get" + propertyName,
  487. new Class[] {});
  488. } catch (final java.lang.NoSuchMethodException ignored) {
  489. try {
  490. getMethod = beanClass.getMethod("is" + propertyName,
  491. new Class[] {});
  492. } catch (final java.lang.NoSuchMethodException ignoredAsWell) {
  493. getMethod = beanClass.getMethod("are" + propertyName,
  494. new Class[] {});
  495. }
  496. }
  497. return getMethod;
  498. }
  499. /**
  500. * Returns the type of the Property. The methods <code>getValue</code> and
  501. * <code>setValue</code> must be compatible with this type: one must be able
  502. * to safely cast the value returned from <code>getValue</code> to the given
  503. * type and pass any variable assignable to this type as an argument to
  504. * <code>setValue</code>.
  505. *
  506. * @return type of the Property
  507. */
  508. @Override
  509. public final Class<? extends T> getType() {
  510. return type;
  511. }
  512. /**
  513. * Tests if the object is in read-only mode. In read-only mode calls to
  514. * <code>setValue</code> will throw <code>ReadOnlyException</code> and will
  515. * not modify the value of the Property.
  516. *
  517. * @return <code>true</code> if the object is in read-only mode,
  518. * <code>false</code> if it's not
  519. */
  520. @Override
  521. public boolean isReadOnly() {
  522. return super.isReadOnly() || (setMethod == null);
  523. }
  524. /**
  525. * Gets the value stored in the Property. The value is resolved by calling
  526. * the specified getter method with the argument specified at instantiation.
  527. *
  528. * @return the value of the Property
  529. */
  530. @Override
  531. public T getValue() {
  532. try {
  533. if (instance == null) {
  534. return null;
  535. } else {
  536. return (T) getMethod.invoke(instance, getArgs);
  537. }
  538. } catch (final Throwable e) {
  539. throw new MethodException(this, e);
  540. }
  541. }
  542. /**
  543. * <p>
  544. * Sets the setter method and getter method argument lists.
  545. * </p>
  546. *
  547. * @param getArgs
  548. * the fixed argument list to be passed to the getter method.
  549. * @param setArgs
  550. * the fixed argument list to be passed to the setter method.
  551. * @param setArgumentIndex
  552. * the index of the argument in <code>setArgs</code> to be
  553. * replaced with <code>newValue</code> when
  554. * {@link #setValue(Object newValue)} is called.
  555. */
  556. public void setArguments(Object[] getArgs, Object[] setArgs,
  557. int setArgumentIndex) {
  558. if (getArgs.length == 0) {
  559. this.getArgs = DEFAULT_GET_ARGS;
  560. } else {
  561. this.getArgs = Arrays.copyOf(getArgs, getArgs.length);
  562. }
  563. if (Arrays.equals(setArgs, DEFAULT_SET_ARGS)) {
  564. this.setArgs = DEFAULT_SET_ARGS;
  565. } else {
  566. this.setArgs = Arrays.copyOf(setArgs, setArgs.length);
  567. }
  568. this.setArgumentIndex = setArgumentIndex;
  569. }
  570. /**
  571. * Sets the value of the property.
  572. *
  573. * Note that since Vaadin 7, no conversions are performed and the value must
  574. * be of the correct type.
  575. *
  576. * @param newValue
  577. * the New value of the property.
  578. * @throws <code>Property.ReadOnlyException</code>
  579. * if the object is in read-only mode.
  580. * @see #invokeSetMethod(Object)
  581. */
  582. @Override
  583. public void setValue(T newValue) throws Property.ReadOnlyException {
  584. // Checks the mode
  585. if (isReadOnly()) {
  586. throw new Property.ReadOnlyException();
  587. }
  588. invokeSetMethod(newValue);
  589. fireValueChange();
  590. }
  591. /**
  592. * Internal method to actually call the setter method of the wrapped
  593. * property.
  594. *
  595. * @param value
  596. */
  597. protected void invokeSetMethod(T value) {
  598. try {
  599. // Construct a temporary argument array only if needed
  600. if (setArgs.length == 1) {
  601. setMethod.invoke(instance, new Object[] { value });
  602. } else {
  603. // Sets the value to argument array
  604. final Object[] args = new Object[setArgs.length];
  605. for (int i = 0; i < setArgs.length; i++) {
  606. args[i] = (i == setArgumentIndex) ? value : setArgs[i];
  607. }
  608. setMethod.invoke(instance, args);
  609. }
  610. } catch (final InvocationTargetException e) {
  611. final Throwable targetException = e.getTargetException();
  612. throw new MethodException(this, targetException);
  613. } catch (final Exception e) {
  614. throw new MethodException(this, e);
  615. }
  616. }
  617. /**
  618. * <code>Exception</code> object that signals that there were problems
  619. * calling or finding the specified getter or setter methods of the
  620. * property.
  621. *
  622. * @author Vaadin Ltd.
  623. * @since 3.0
  624. */
  625. @SuppressWarnings("rawtypes")
  626. @Deprecated
  627. // Exceptions cannot be parameterized, ever.
  628. public static class MethodException extends RuntimeException {
  629. /**
  630. * The method property from which the exception originates from
  631. */
  632. private final Property property;
  633. /**
  634. * Cause of the method exception
  635. */
  636. private Throwable cause;
  637. /**
  638. * Constructs a new <code>MethodException</code> with the specified
  639. * detail message.
  640. *
  641. * @param property
  642. * the property.
  643. * @param msg
  644. * the detail message.
  645. */
  646. public MethodException(Property property, String msg) {
  647. super(msg);
  648. this.property = property;
  649. }
  650. /**
  651. * Constructs a new <code>MethodException</code> from another exception.
  652. *
  653. * @param property
  654. * the property.
  655. * @param cause
  656. * the cause of the exception.
  657. */
  658. public MethodException(Property property, Throwable cause) {
  659. this.property = property;
  660. this.cause = cause;
  661. }
  662. /**
  663. * @see java.lang.Throwable#getCause()
  664. */
  665. @Override
  666. public Throwable getCause() {
  667. return cause;
  668. }
  669. /**
  670. * Gets the method property this exception originates from.
  671. *
  672. * @return MethodProperty or null if not a valid MethodProperty
  673. */
  674. public MethodProperty getMethodProperty() {
  675. return (property instanceof MethodProperty)
  676. ? (MethodProperty) property : null;
  677. }
  678. /**
  679. * Gets the method property this exception originates from.
  680. *
  681. * @return Property from which the exception originates
  682. */
  683. public Property getProperty() {
  684. return property;
  685. }
  686. }
  687. /**
  688. * Sends a value change event to all registered listeners.
  689. *
  690. * Public for backwards compatibility, visibility may be reduced in future
  691. * versions.
  692. */
  693. @Override
  694. public void fireValueChange() {
  695. super.fireValueChange();
  696. }
  697. private static final Logger getLogger() {
  698. return Logger.getLogger(MethodProperty.class.getName());
  699. }
  700. }