選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

ColumnProperty.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*
  2. * Copyright 2011 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.data.util.sqlcontainer;
  17. import java.sql.Date;
  18. import java.sql.Time;
  19. import java.sql.Timestamp;
  20. import java.util.logging.Logger;
  21. import com.vaadin.data.Property;
  22. import com.vaadin.data.util.converter.Converter.ConversionException;
  23. /**
  24. * ColumnProperty represents the value of one column in a RowItem. In addition
  25. * to the value, ColumnProperty also contains some basic column attributes such
  26. * as nullability status, read-only status and data type.
  27. *
  28. * Note that depending on the QueryDelegate in use this does not necessarily map
  29. * into an actual column in a database table.
  30. */
  31. final public class ColumnProperty implements Property {
  32. private static final long serialVersionUID = -3694463129581802457L;
  33. private RowItem owner;
  34. private String propertyId;
  35. private boolean readOnly;
  36. private boolean allowReadOnlyChange = true;
  37. private boolean nullable = true;
  38. private Object value;
  39. private Object changedValue;
  40. private Class<?> type;
  41. private boolean modified;
  42. private boolean versionColumn;
  43. private boolean primaryKey = false;
  44. /**
  45. * Prevent instantiation without required parameters.
  46. */
  47. @SuppressWarnings("unused")
  48. private ColumnProperty() {
  49. }
  50. /**
  51. * Deprecated constructor for ColumnProperty. If this is used the primary
  52. * keys are not identified correctly in some cases for some databases (i.e.
  53. * Oracle). See http://dev.vaadin.com/ticket/9145.
  54. *
  55. * @param propertyId
  56. * @param readOnly
  57. * @param allowReadOnlyChange
  58. * @param nullable
  59. * @param value
  60. * @param type
  61. *
  62. * @deprecated As of 7.0. Use
  63. * {@link #ColumnProperty(String, boolean, boolean, boolean, boolean, Object, Class)
  64. * instead
  65. */
  66. @Deprecated
  67. public ColumnProperty(String propertyId, boolean readOnly,
  68. boolean allowReadOnlyChange, boolean nullable, Object value,
  69. Class<?> type) {
  70. this(propertyId, readOnly, allowReadOnlyChange, nullable, false, value,
  71. type);
  72. }
  73. /**
  74. * Creates a new ColumnProperty instance.
  75. *
  76. * @param propertyId
  77. * The ID of this property.
  78. * @param readOnly
  79. * Whether this property is read-only.
  80. * @param allowReadOnlyChange
  81. * Whether the read-only status of this property can be changed.
  82. * @param nullable
  83. * Whether this property accepts null values.
  84. * @param primaryKey
  85. * Whether this property corresponds to a database primary key.
  86. * @param value
  87. * The value of this property.
  88. * @param type
  89. * The type of this property.
  90. */
  91. public ColumnProperty(String propertyId, boolean readOnly,
  92. boolean allowReadOnlyChange, boolean nullable, boolean primaryKey,
  93. Object value, Class<?> type) {
  94. if (propertyId == null) {
  95. throw new IllegalArgumentException("Properties must be named.");
  96. }
  97. if (type == null) {
  98. throw new IllegalArgumentException("Property type must be set.");
  99. }
  100. this.propertyId = propertyId;
  101. this.type = type;
  102. this.value = value;
  103. this.allowReadOnlyChange = allowReadOnlyChange;
  104. this.nullable = nullable;
  105. this.readOnly = readOnly;
  106. this.primaryKey = primaryKey;
  107. }
  108. /**
  109. * Returns the current value for this property. To get the previous value
  110. * (if one exists) for a modified property use {@link #getOldValue()}.
  111. *
  112. * @return
  113. */
  114. @Override
  115. public Object getValue() {
  116. if (isModified()) {
  117. return changedValue;
  118. }
  119. return value;
  120. }
  121. /**
  122. * Returns the original non-modified value of this property if it has been
  123. * modified.
  124. *
  125. * @return The original value if <code>isModified()</code> is true,
  126. * <code>getValue()</code> otherwise.
  127. */
  128. public Object getOldValue() {
  129. return value;
  130. }
  131. @Override
  132. public void setValue(Object newValue) throws ReadOnlyException,
  133. ConversionException {
  134. if (newValue == null && !nullable) {
  135. throw new NotNullableException(
  136. "Null values are not allowed for this property.");
  137. }
  138. if (readOnly) {
  139. throw new ReadOnlyException(
  140. "Cannot set value for read-only property.");
  141. }
  142. /* Check if this property is a date property. */
  143. boolean isDateProperty = Time.class.equals(getType())
  144. || Date.class.equals(getType())
  145. || Timestamp.class.equals(getType());
  146. if (newValue != null) {
  147. /* Handle SQL dates, times and Timestamps given as java.util.Date */
  148. if (isDateProperty) {
  149. /*
  150. * Try to get the millisecond value from the new value of this
  151. * property. Possible type to convert from is java.util.Date.
  152. */
  153. long millis = 0;
  154. if (newValue instanceof java.util.Date) {
  155. millis = ((java.util.Date) newValue).getTime();
  156. /*
  157. * Create the new object based on the millisecond value,
  158. * according to the type of this property.
  159. */
  160. if (Time.class.equals(getType())) {
  161. newValue = new Time(millis);
  162. } else if (Date.class.equals(getType())) {
  163. newValue = new Date(millis);
  164. } else if (Timestamp.class.equals(getType())) {
  165. newValue = new Timestamp(millis);
  166. }
  167. }
  168. }
  169. if (!getType().isAssignableFrom(newValue.getClass())) {
  170. throw new IllegalArgumentException(
  171. "Illegal value type for ColumnProperty");
  172. }
  173. /*
  174. * If the value to be set is the same that has already been set, do
  175. * not set it again.
  176. */
  177. if (isValueAlreadySet(newValue)) {
  178. return;
  179. }
  180. }
  181. /* Set the new value and notify container of the change. */
  182. changedValue = newValue;
  183. modified = true;
  184. owner.getContainer().itemChangeNotification(owner);
  185. }
  186. private boolean isValueAlreadySet(Object newValue) {
  187. Object referenceValue = isModified() ? changedValue : value;
  188. return (isNullable() && newValue == null && referenceValue == null)
  189. || newValue.equals(referenceValue);
  190. }
  191. @Override
  192. public Class<?> getType() {
  193. return type;
  194. }
  195. @Override
  196. public boolean isReadOnly() {
  197. return readOnly;
  198. }
  199. /**
  200. * Returns whether the read-only status of this property can be changed
  201. * using {@link #setReadOnly(boolean)}.
  202. * <p>
  203. * Used to prevent setting to read/write mode a property that is not allowed
  204. * to be written by the underlying database. Also used for values like
  205. * VERSION and AUTO_INCREMENT fields that might be set to read-only by the
  206. * container but the database still allows writes.
  207. *
  208. * @return true if the read-only status can be changed, false otherwise.
  209. */
  210. public boolean isReadOnlyChangeAllowed() {
  211. return allowReadOnlyChange;
  212. }
  213. @Override
  214. public void setReadOnly(boolean newStatus) {
  215. if (allowReadOnlyChange) {
  216. readOnly = newStatus;
  217. }
  218. }
  219. public boolean isPrimaryKey() {
  220. return primaryKey;
  221. }
  222. public String getPropertyId() {
  223. return propertyId;
  224. }
  225. /**
  226. * Returns the value of the Property in human readable textual format.
  227. *
  228. * @see java.lang.Object#toString()
  229. * @deprecated As of 7.0, use {@link #getValue()} instead and possibly
  230. * toString on that
  231. */
  232. @Deprecated
  233. @Override
  234. public String toString() {
  235. getLogger()
  236. .warning(
  237. "You are using ColumnProperty.toString() instead of getValue() to get the value for a "
  238. + getClass().getSimpleName()
  239. + ". This will not be supported starting from Vaadin 7.1 "
  240. + "(your debugger might call toString() and cause this message to appear).");
  241. Object v = getValue();
  242. if (v == null) {
  243. return null;
  244. }
  245. return v.toString();
  246. }
  247. private static Logger getLogger() {
  248. return Logger.getLogger(ColumnProperty.class.getName());
  249. }
  250. public void setOwner(RowItem owner) {
  251. if (owner == null) {
  252. throw new IllegalArgumentException("Owner can not be set to null.");
  253. }
  254. if (this.owner != null) {
  255. throw new IllegalStateException(
  256. "ColumnProperties can only be bound once.");
  257. }
  258. this.owner = owner;
  259. }
  260. public boolean isModified() {
  261. return modified;
  262. }
  263. public boolean isVersionColumn() {
  264. return versionColumn;
  265. }
  266. public void setVersionColumn(boolean versionColumn) {
  267. this.versionColumn = versionColumn;
  268. }
  269. public boolean isNullable() {
  270. return nullable;
  271. }
  272. /**
  273. * Return whether the value of this property should be persisted to the
  274. * database.
  275. *
  276. * @return true if the value should be written to the database, false
  277. * otherwise.
  278. */
  279. public boolean isPersistent() {
  280. if (isVersionColumn()) {
  281. return false;
  282. } else if (isReadOnlyChangeAllowed() && !isReadOnly()) {
  283. return true;
  284. } else {
  285. return false;
  286. }
  287. }
  288. /**
  289. * Returns whether or not this property is used as a row identifier.
  290. *
  291. * @return true if the property is a row identifier, false otherwise.
  292. */
  293. public boolean isRowIdentifier() {
  294. return isPrimaryKey() || isVersionColumn();
  295. }
  296. /**
  297. * An exception that signals that a <code>null</code> value was passed to
  298. * the <code>setValue</code> method, but the value of this property can not
  299. * be set to <code>null</code>.
  300. */
  301. @SuppressWarnings("serial")
  302. public class NotNullableException extends RuntimeException {
  303. /**
  304. * Constructs a new <code>NotNullableException</code> without a detail
  305. * message.
  306. */
  307. public NotNullableException() {
  308. }
  309. /**
  310. * Constructs a new <code>NotNullableException</code> with the specified
  311. * detail message.
  312. *
  313. * @param msg
  314. * the detail message
  315. */
  316. public NotNullableException(String msg) {
  317. super(msg);
  318. }
  319. /**
  320. * Constructs a new <code>NotNullableException</code> from another
  321. * exception.
  322. *
  323. * @param cause
  324. * The cause of the failure
  325. */
  326. public NotNullableException(Throwable cause) {
  327. super(cause);
  328. }
  329. }
  330. public void commit() {
  331. if (isModified()) {
  332. modified = false;
  333. value = changedValue;
  334. }
  335. }
  336. }