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.direct;
17
18 import java.util.NoSuchElementException;
19 import java.util.Set;
20
21 import org.joda.beans.Bean;
22 import org.joda.beans.JodaBeanUtils;
23 import org.joda.beans.Property;
24
25 /**
26 * A bean implementation designed for use by the code generator.
27 * <p>
28 * This implementation uses direct access via {@link #propertyGet(String, boolean)} and
29 * {@link #propertySet(String, Object, boolean)} to avoid reflection.
30 * <p>
31 * For code generation, the bean must directly extend this class and have a
32 * no-arguments constructor.
33 *
34 * @author Stephen Colebourne
35 */
36 public abstract class DirectBean implements Bean {
37
38 @Override
39 public <R> Property<R> property(String propertyName) {
40 return metaBean().<R>metaProperty(propertyName).createProperty(this);
41 }
42
43 @Override
44 public Set<String> propertyNames() {
45 return metaBean().metaPropertyMap().keySet();
46 }
47
48 //-------------------------------------------------------------------------
49 /**
50 * Gets the value of the property.
51 *
52 * @param propertyName the property name, not null
53 * @param quiet true to return null if unable to read
54 * @return the value of the property, may be null
55 * @throws NoSuchElementException if the property name is invalid
56 */
57 protected Object propertyGet(String propertyName, boolean quiet) {
58 throw new NoSuchElementException("Unknown property: " + propertyName);
59 }
60
61 /**
62 * Sets the value of the property.
63 *
64 * @param propertyName the property name, not null
65 * @param value the value of the property, may be null
66 * @param quiet true to take no action if unable to write
67 * @throws NoSuchElementException if the property name is invalid
68 */
69 protected void propertySet(String propertyName, Object value, boolean quiet) {
70 throw new NoSuchElementException("Unknown property: " + propertyName);
71 }
72
73 /**
74 * Validates the values of the properties.
75 *
76 * @throws RuntimeException if a property is invalid
77 */
78 protected void validate() {
79 }
80
81 //-----------------------------------------------------------------------
82 @Override
83 public boolean equals(Object obj) {
84 if (obj == this) {
85 return true;
86 }
87 if (obj != null && getClass() == obj.getClass()) {
88 DirectBean other = (DirectBean) obj;
89 for (String name : propertyNames()) {
90 Object value1 = propertyGet(name, true);
91 Object value2 = other.propertyGet(name, true);
92 if (JodaBeanUtils.equal(value1, value2) == false) {
93 return false;
94 }
95 }
96 return true;
97 }
98 return false;
99 }
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 }