2 * DemosceneMusic - Base.java - Copyright © 2012 David Roden
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package net.pterodactylus.demoscenemusic.data;
20 import java.util.HashMap;
22 import java.util.Map.Entry;
25 * Base implementation of a data container. It stores the ID of a container and
26 * can contain arbitrary attributes.
28 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
30 public class DefaultBase implements Base {
32 /** The ID of the data container. */
33 private final String id;
35 /** The attributes of the data container. */
36 private final Map<String, Value<?>> attributes = new HashMap<String, Value<?>>();
38 /** The properties of the data container. */
39 private final Properties properties = new Properties();
42 * Creates a new data container with the given ID.
45 * The ID of the data container
47 protected DefaultBase(String id) {
59 public String getId() {
67 public Properties getProperties() {
72 * Returns whether the data container contains an attribute with the given
76 * The name of the attribute to check for
77 * @return {@code true} if this data container contains an attribute with
78 * the given name, {@code false} otherwise
80 protected boolean hasValue(String name) {
81 return attributes.containsKey(name);
85 * Returns the value of the attribute with the given name. If no value for
86 * the given attribute exists, one will be created, stored, and returned.
89 * The type of the value to return
91 * The name of the attribute to get
93 * The class of the value
94 * @return The value of the attribute
96 @SuppressWarnings({ "unchecked" })
97 protected <T> Value<T> getValue(String name, Class<T> clazz) {
98 if (!attributes.containsKey(name)) {
99 attributes.put(name, new Value<T>());
101 return (Value<T>) attributes.get(name);
105 * Returns whether any of the attributes of this data container is dirty,
106 * i.e. it was modified after its initial inception.
108 * @return {@code true} if any attribute of this data container was modified
110 protected boolean isDirty() {
111 for (Value<?> value : attributes.values()) {
112 if (value.isDirty()) {
127 public int hashCode() {
128 return getId().hashCode();
135 public boolean equals(Object obj) {
136 if (!(obj instanceof Base)) {
139 return getId().equals(((Base) obj).getId());
146 public String toString() {
147 StringBuilder stringBuilder = new StringBuilder();
148 stringBuilder.append(getClass().getName());
149 stringBuilder.append('[').append("id=").append(getId());
150 for (Entry<String, Value<?>> attributeEntry : attributes.entrySet()) {
151 stringBuilder.append(',').append(attributeEntry.getKey()).append('=').append(attributeEntry.getValue().get());
153 stringBuilder.append(']');
154 return stringBuilder.toString();
158 * Container for an attribute value stored in a data container.
160 * @see DefaultBase#attributes
162 * The type of the value
163 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
165 protected static class Value<T> {
167 /** The original value. */
170 /** Whether the original value has been set. */
171 private boolean originalSet;
173 /** The current value. */
181 * Returns the current value.
183 * @return The current value
190 * Sets the current value. If no original value has yet been set, the
191 * given value is also stored as original value.
197 public Value<T> set(T value) {
207 * Returns whether the value of this value does not equal its original
210 * @return {@code true} if the current value is not equal to the
211 * original value, {@code false} if it is equal to the original
214 public boolean isDirty() {
215 return (original != null) ? !original.equals(current) : current != null;
219 * Commits the current value, i.e. sets the original value to the
224 public Value<T> commit() {