001 /*
002 * Copyright 2001-2013 Stephen Colebourne
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.joda.beans.impl;
017
018 import org.joda.beans.Bean;
019 import org.joda.beans.MetaProperty;
020 import org.joda.beans.Property;
021
022 /**
023 * A property that binds a {@code Bean} to a {@code MetaProperty}.
024 * <p>
025 * This is the standard implementation of a property.
026 * It defers the strategy of getting and setting the value to the meta-property.
027 * <p>
028 * This implementation is also a map entry to aid performance in maps.
029 *
030 * @param <P> the type of the property content
031 * @author Stephen Colebourne
032 */
033 public final class BasicProperty<P> implements Property<P> {
034
035 /** The bean that the property is bound to. */
036 private final Bean bean;
037 /** The meta-property that the property is bound to. */
038 private final MetaProperty<P> metaProperty;
039
040 /**
041 * Factory to create a property avoiding duplicate generics.
042 *
043 * @param bean the bean that the property is bound to, not null
044 * @param metaProperty the meta property, not null
045 */
046 public static <P> BasicProperty<P> of(Bean bean, MetaProperty<P> metaProperty) {
047 return new BasicProperty<P>(bean, metaProperty);
048 }
049
050 /**
051 * Creates a property binding the bean to the meta-property.
052 *
053 * @param bean the bean that the property is bound to, not null
054 * @param metaProperty the meta property, not null
055 */
056 private BasicProperty(Bean bean, MetaProperty<P> metaProperty) {
057 if (bean == null) {
058 throw new NullPointerException("Bean must not be null");
059 }
060 if (metaProperty == null) {
061 throw new NullPointerException("MetaProperty must not be null");
062 }
063 this.bean = bean;
064 this.metaProperty = metaProperty;
065 }
066
067 //-----------------------------------------------------------------------
068 @SuppressWarnings("unchecked")
069 @Override
070 public <B extends Bean> B bean() {
071 return (B) bean;
072 }
073
074 @Override
075 public MetaProperty<P> metaProperty() {
076 return metaProperty;
077 }
078
079 @Override
080 public String name() {
081 return metaProperty.name();
082 }
083
084 //-----------------------------------------------------------------------
085 @Override
086 public P get() {
087 return metaProperty.get(bean);
088 }
089
090 @Override
091 public void set(Object value) {
092 metaProperty.set(bean, value);
093 }
094
095 @Override
096 public P put(Object value) {
097 return metaProperty.put(bean, value);
098 }
099
100 //-----------------------------------------------------------------------
101 @Override
102 public boolean equals(Object obj) {
103 if (obj == this) {
104 return true;
105 }
106 if (obj instanceof Property) {
107 Property<?> other = (Property<?>) obj;
108 if (metaProperty.equals(other.metaProperty())) {
109 Object a = get();
110 Object b = other.get();
111 return a == null ? b == null : a.equals(b);
112 }
113 }
114 return false;
115 }
116
117 @Override
118 public int hashCode() {
119 P value = get();
120 return metaProperty.hashCode() ^ (value == null ? 0 : value.hashCode());
121 }
122
123 /**
124 * Returns a string that summarises the property.
125 *
126 * @return a summary string, not null
127 */
128 @Override
129 public String toString() {
130 return metaProperty + "=" + get();
131 }
132
133 }