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.direct;
017
018 import java.util.NoSuchElementException;
019 import java.util.Set;
020
021 import org.joda.beans.Bean;
022 import org.joda.beans.JodaBeanUtils;
023 import org.joda.beans.Property;
024
025 /**
026 * A bean implementation designed for use by the code generator.
027 * <p>
028 * This implementation uses direct access via {@link #propertyGet(String)} and
029 * {@link #propertySet(String, Object)} to avoid reflection.
030 * <p>
031 * For code generation, the bean must directly extend this class and have a
032 * no-arguments constructor.
033 *
034 * @author Stephen Colebourne
035 */
036 public abstract class DirectBean implements Bean {
037
038 @Override
039 public <R> Property<R> property(String propertyName) {
040 return metaBean().<R>metaProperty(propertyName).createProperty(this);
041 }
042
043 @Override
044 public Set<String> propertyNames() {
045 return metaBean().metaPropertyMap().keySet();
046 }
047
048 //-------------------------------------------------------------------------
049 /**
050 * Gets the value of the property.
051 *
052 * @param propertyName the property name, not null
053 * @param quiet true to return null if unable to read
054 * @return the value of the property, may be null
055 * @throws NoSuchElementException if the property name is invalid
056 */
057 protected Object propertyGet(String propertyName, boolean quiet) {
058 throw new NoSuchElementException("Unknown property: " + propertyName);
059 }
060
061 /**
062 * Sets the value of the property.
063 *
064 * @param propertyName the property name, not null
065 * @param value the value of the property, may be null
066 * @param quiet true to take no action if unable to write
067 * @throws NoSuchElementException if the property name is invalid
068 */
069 protected void propertySet(String propertyName, Object value, boolean quiet) {
070 throw new NoSuchElementException("Unknown property: " + propertyName);
071 }
072
073 /**
074 * Validates the values of the properties.
075 *
076 * @throws RuntimeException if a property is invalid
077 */
078 protected void validate() {
079 }
080
081 //-----------------------------------------------------------------------
082 @Override
083 public boolean equals(Object obj) {
084 if (obj == this) {
085 return true;
086 }
087 if (obj != null && getClass() == obj.getClass()) {
088 DirectBean other = (DirectBean) obj;
089 for (String name : propertyNames()) {
090 Object value1 = propertyGet(name, true);
091 Object value2 = other.propertyGet(name, true);
092 if (JodaBeanUtils.equal(value1, value2) == false) {
093 return false;
094 }
095 }
096 return true;
097 }
098 return false;
099 }
100
101 @Override
102 public int hashCode() {
103 int hash = getClass().hashCode();
104 Set<String> names = propertyNames();
105 for (String name : names) {
106 Object value = propertyGet(name, true);
107 hash += JodaBeanUtils.hashCode(value);
108 }
109 return hash;
110 }
111
112 @Override
113 public String toString() {
114 Set<String> names = propertyNames();
115 StringBuilder buf = new StringBuilder((names.size()) * 32 + 32);
116 buf.append(getClass().getSimpleName());
117 buf.append('{');
118 if (names.size() > 0) {
119 for (String name : names) {
120 Object value = propertyGet(name, true);
121 buf.append(name).append('=').append(value).append(',').append(' ');
122 }
123 buf.setLength(buf.length() - 2);
124 }
125 buf.append('}');
126 return buf.toString();
127 }
128
129 }