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<?>>();
39 * Creates a new data container with the given ID.
42 * The ID of the data container
44 protected DefaultBase(String id) {
56 public String getId() {
61 * Returns whether the data container contains an attribute with the given
65 * The name of the attribute to check for
66 * @return {@code true} if this data container contains an attribute with
67 * the given name, {@code false} otherwise
69 protected boolean hasValue(String name) {
70 return attributes.containsKey(name);
74 * Returns the value of the attribute with the given name. If no value for
75 * the given attribute exists, one will be created, stored, and returned.
78 * The type of the value to return
80 * The name of the attribute to get
82 * The class of the value
83 * @return The value of the attribute
85 @SuppressWarnings({ "unchecked" })
86 protected <T> Value<T> getValue(String name, Class<T> clazz) {
87 if (!attributes.containsKey(name)) {
88 attributes.put(name, new Value<T>());
90 return (Value<T>) attributes.get(name);
94 * Returns whether any of the attributes of this data container is dirty,
95 * i.e. it was modified after its initial inception.
97 * @return {@code true} if any attribute of this data container was modified
99 protected boolean isDirty() {
100 for (Value<?> value : attributes.values()) {
101 if (value.isDirty()) {
116 public int hashCode() {
117 return getId().hashCode();
124 public boolean equals(Object obj) {
125 if (!(obj instanceof Base)) {
128 return getId().equals(((Base) obj).getId());
135 public String toString() {
136 StringBuilder stringBuilder = new StringBuilder();
137 stringBuilder.append(getClass().getName());
138 stringBuilder.append('[').append("id=").append(getId());
139 for (Entry<String, Value<?>> attributeEntry : attributes.entrySet()) {
140 stringBuilder.append(',').append(attributeEntry.getKey()).append('=').append(attributeEntry.getValue().get());
142 stringBuilder.append(']');
143 return stringBuilder.toString();
147 * Container for an attribute value stored in a data container.
149 * @see DefaultBase#attributes
151 * The type of the value
152 * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
154 protected static class Value<T> {
156 /** The original value. */
159 /** Whether the original value has been set. */
160 private boolean originalSet;
162 /** The current value. */
170 * Returns the current value.
172 * @return The current value
179 * Sets the current value. If no original value has yet been set, the
180 * given value is also stored as original value.
186 public Value<T> set(T value) {
196 * Returns whether the value of this value does not equal its original
199 * @return {@code true} if the current value is not equal to the
200 * original value, {@code false} if it is equal to the original
203 public boolean isDirty() {
204 return (original != null) ? !original.equals(current) : current != null;
208 * Commits the current value, i.e. sets the original value to the
213 public Value<T> commit() {