1 /*
2 * Copyright 2001-2013 Stephen Colebourne
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of 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,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.joda.beans.impl;
17
18 import org.joda.beans.Bean;
19 import org.joda.beans.MetaProperty;
20 import org.joda.beans.Property;
21
22 /**
23 * A property that binds a {@code Bean} to a {@code MetaProperty}.
24 * <p>
25 * This is the standard implementation of a property.
26 * It defers the strategy of getting and setting the value to the meta-property.
27 * <p>
28 * This implementation is also a map entry to aid performance in maps.
29 *
30 * @param <P> the type of the property content
31 * @author Stephen Colebourne
32 */
33 public final class BasicProperty<P> implements Property<P> {
34
35 /** The bean that the property is bound to. */
36 private final Bean bean;
37 /** The meta-property that the property is bound to. */
38 private final MetaProperty<P> metaProperty;
39
40 /**
41 * Factory to create a property avoiding duplicate generics.
42 *
43 * @param <P> the property type
44 * @param bean the bean that the property is bound to, not null
45 * @param metaProperty the meta property, not null
46 * @return the property, not null
47 */
48 public static <P> BasicProperty<P> of(Bean bean, MetaProperty<P> metaProperty) {
49 return new BasicProperty<P>(bean, metaProperty);
50 }
51
52 /**
53 * Creates a property binding the bean to the meta-property.
54 *
55 * @param bean the bean that the property is bound to, not null
56 * @param metaProperty the meta property, not null
57 */
58 private BasicProperty(Bean bean, MetaProperty<P> metaProperty) {
59 if (bean == null) {
60 throw new NullPointerException("Bean must not be null");
61 }
62 if (metaProperty == null) {
63 throw new NullPointerException("MetaProperty must not be null");
64 }
65 this.bean = bean;
66 this.metaProperty = metaProperty;
67 }
68
69 //-----------------------------------------------------------------------
70 @SuppressWarnings("unchecked")
71 @Override
72 public <B extends Bean> B bean() {
73 return (B) bean;
74 }
75
76 @Override
77 public MetaProperty<P> metaProperty() {
78 return metaProperty;
79 }
80
81 @Override
82 public String name() {
83 return metaProperty.name();
84 }
85
86 //-----------------------------------------------------------------------
87 @Override
88 public P get() {
89 return metaProperty.get(bean);
90 }
91
92 @Override
93 public void set(Object value) {
94 metaProperty.set(bean, value);
95 }
96
97 @Override
98 public P put(Object value) {
99 return metaProperty.put(bean, value);
100 }
101
102 //-----------------------------------------------------------------------
103 @Override
104 public boolean equals(Object obj) {
105 if (obj == this) {
106 return true;
107 }
108 if (obj instanceof Property) {
109 Property<?> other = (Property<?>) obj;
110 if (metaProperty.equals(other.metaProperty())) {
111 Object a = get();
112 Object b = other.get();
113 return a == null ? b == null : a.equals(b);
114 }
115 }
116 return false;
117 }
118
119 @Override
120 public int hashCode() {
121 P value = get();
122 return metaProperty.hashCode() ^ (value == null ? 0 : value.hashCode());
123 }
124
125 /**
126 * Returns a string that summarises the property.
127 *
128 * @return a summary string, not null
129 */
130 @Override
131 public String toString() {
132 return metaProperty + "=" + get();
133 }
134
135 }