001 /*
002 * Copyright 2001-2010 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;
017
018 import java.util.Map.Entry;
019
020 /**
021 * A property that binds a {@code Bean} to a {@code MetaProperty}.
022 * <p>
023 * This is the standard implementation of a property.
024 * It defers the strategy of getting and setting the value to the meta-property.
025 * <p>
026 * This implementation is also a map entry to aid performance in {@code }
027 *
028 * @param <B> the type of the bean
029 * @param <P> the type of the property content
030 * @author Stephen Colebourne
031 */
032 public final class StandardProperty<B, P> implements Property<B, P>, Entry<String, Property<B, P>> {
033
034 /** The bean that the property is bound to. */
035 private final B bean;
036 /** The meta-property that the property is bound to. */
037 private final MetaProperty<B, P> metaProperty;
038
039 /**
040 * Factory to create a property avoiding duplicate generics.
041 *
042 * @param bean the bean that the property is bound to, not null
043 * @param metaProperty the meta property, not null
044 */
045 public static <B, P> StandardProperty<B, P> of(B bean, MetaProperty<B, P> metaProperty) {
046 return new StandardProperty<B, P>(bean, metaProperty);
047 }
048
049 /**
050 * Creates a property binding the bean to the meta-property.
051 *
052 * @param bean the bean that the property is bound to, not null
053 * @param metaProperty the meta property, not null
054 */
055 private StandardProperty(B bean, MetaProperty<B, P> metaProperty) {
056 Beans.checkNotNull(bean, "Bean must not be null");
057 Beans.checkNotNull(metaProperty, "MetaProperty must not be null");
058 this.bean = bean;
059 this.metaProperty = metaProperty;
060 }
061
062 //-----------------------------------------------------------------------
063 @Override
064 public B bean() {
065 return bean;
066 }
067
068 @Override
069 public MetaProperty<B, P> metaProperty() {
070 return metaProperty;
071 }
072
073 //-----------------------------------------------------------------------
074 @Override
075 public P get() {
076 return metaProperty().get(bean());
077 }
078
079 @Override
080 public void set(P value) {
081 metaProperty().set(bean(), value);
082 }
083
084 //-----------------------------------------------------------------------
085 @Override
086 public String getKey() {
087 return metaProperty().name();
088 }
089
090 @Override
091 public Property<B, P> getValue() {
092 return this;
093 }
094
095 @Override
096 public Property<B, P> setValue(Property<B, P> value) {
097 throw new UnsupportedOperationException("Unmodifiable");
098 }
099
100 //-----------------------------------------------------------------------
101 public boolean equals(Object obj) {
102 // specified by Map.Entry
103 if (obj instanceof Entry<?, ?>) {
104 Entry<?, ?> other = (Entry<?, ?>) obj;
105 return (this.getKey() == null ? other.getKey() == null : this.getKey().equals(other.getKey())) &&
106 (this.getValue() == null ? other.getValue() == null : this.getValue().equals(other.getValue()));
107 }
108 return false;
109 }
110
111 public int hashCode() {
112 // specified by Map.Entry
113 return (getKey()==null ? 0 : getKey().hashCode()) ^ (getValue()==null ? 0 : getValue().hashCode());
114 }
115
116 /**
117 * Returns a string that summarizes the property.
118 *
119 * @return a summary string, never null
120 */
121 @Override
122 public String toString() {
123 return metaProperty().name() + ":" + get();
124 }
125
126 }