001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.graph.implementations;
033
034import java.util.ArrayList;
035import java.util.Iterator;
036import java.util.Map;
037
038import org.graphstream.graph.Element;
039
040/**
041 * An implementation of an {@link org.graphstream.graph.Element}.
042 * 
043 * <p>
044 * It allows only one attribute and has no internal map structure. <b>It is not
045 * used and may be removed.</b>
046 * </p>
047 * 
048 */
049public abstract class OneAttributeElement implements Element {
050        // Constants
051
052        // Attributes
053
054        /**
055         * Tag of this element.
056         */
057        protected String id;
058
059        /**
060         * The only one attribute
061         */
062        Object attribute = null;
063
064        // Constructors
065
066        /**
067         * New element.
068         * 
069         * @param id
070         *            The unique identifier of this element.
071         */
072        public OneAttributeElement(String id) {
073                assert id != null : "Graph elements cannot have a null identifier";
074                this.id = id;
075        }
076
077        // Accessors
078
079        public String getId() {
080                return id;
081        }
082
083        @SuppressWarnings("all")
084        public <T> T getAttribute(String key) {
085                return (T) attribute;
086        }
087
088        @SuppressWarnings("all")
089        public <T> T getFirstAttributeOf(String... keys) {
090                return (T) attribute;
091        }
092
093        @SuppressWarnings("all")
094        public <T> T getAttribute(String key, Class<T> clazz) {
095                return (T) attribute;
096        }
097
098        @SuppressWarnings("all")
099        public <T> T getFirstAttributeOf(Class<T> clazz, String... keys) {
100                return (T) attribute;
101        }
102
103        public CharSequence getLabel(String key) {
104                if (attribute != null && attribute instanceof CharSequence)
105                        return (CharSequence) attribute;
106                return null;
107        }
108
109        public double getNumber(String key) {
110                if (attribute != null && attribute instanceof Number)
111                        return ((Number) attribute).doubleValue();
112
113                return Double.NaN;
114        }
115
116        @SuppressWarnings("unchecked")
117        public ArrayList<? extends Number> getVector(String key) {
118                if (attribute != null && attribute instanceof ArrayList)
119                        return ((ArrayList<? extends Number>) attribute);
120
121                return null;
122        }
123
124        public boolean hasAttribute(String key) {
125
126                return true;
127        }
128
129        public boolean hasAttribute(String key, Class<?> clazz) {
130                if (attribute != null)
131                        return (clazz.isInstance(attribute));
132                return false;
133        }
134
135        public boolean hasLabel(String key) {
136                if (attribute != null)
137                        return (attribute instanceof CharSequence);
138
139                return false;
140        }
141
142        public boolean hasNumber(String key) {
143                if (attribute != null)
144                        return (attribute instanceof Number);
145
146                return false;
147        }
148
149        public boolean hasVector(String key) {
150                if (attribute != null && attribute instanceof ArrayList<?>)
151                        return true;
152
153                return false;
154        }
155
156        public Iterator<String> getAttributeKeyIterator() {
157                return null;
158        }
159
160        public Map<String, Object> getAttributeMap() {
161                return null;
162        }
163
164        /**
165         * Override the Object method
166         */
167        @Override
168        public String toString() {
169                return id;
170        }
171
172        // Commands
173
174        public void clearAttributes() {
175                attribute = null;
176        }
177
178        public void addAttribute(String attribute, Object value) {
179                this.attribute = value;
180                // System.out.println(attribute+" = "+value.toString());
181        }
182
183        public void changeAttribute(String attribute, Object value) {
184                addAttribute(attribute, value);
185                // System.out.println(attribute+" = "+value.toString());
186
187        }
188
189        public void addAttributes(Map<String, Object> attributes) {
190                // System.out.println(attributes.toString());
191                if (attributes.size() >= 1)
192                        addAttribute("", attributes.get((attributes.keySet().toArray()[0])));
193
194        }
195
196        public void removeAttribute(String attribute) {
197                this.attribute = null;
198        }
199
200        public static enum AttributeChangeEvent {
201                ADD, CHANGE, REMOVE
202        };
203
204        /**
205         * Called for each change in the attribute set. This method must be
206         * implemented by sub-elements in order to send events to the graph
207         * listeners.
208         * 
209         * @param sourceId
210         *            The source of the change.
211         * @param timeId
212         *            The source time of the change, for synchronization.
213         * @param attribute
214         *            The attribute name that changed.
215         * @param event
216         *            The type of event among ADD, CHANGE and REMOVE.
217         * @param oldValue
218         *            The old value of the attribute, null if the attribute was
219         *            added.
220         * @param newValue
221         *            The new value of the attribute, null if the attribute is about
222         *            to be removed.
223         */
224        protected abstract void attributeChanged(String sourceId, long timeId,
225                        String attribute, AttributeChangeEvent event, Object oldValue,
226                        Object newValue);
227}