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 * GraphStream is a library whose purpose is to handle static or dynamic
010 * graph, create them from scratch, file or any source and display them.
011 * 
012 * This program is free software distributed under the terms of two licenses, the
013 * CeCILL-C license that fits European law, and the GNU Lesser General Public
014 * License. You can  use, modify and/ or redistribute the software under the terms
015 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
016 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
017 * the Free Software Foundation, either version 3 of the License, or (at your
018 * option) any later version.
019 * 
020 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
021 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
022 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
023 * 
024 * You should have received a copy of the GNU Lesser General Public License
025 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
026 * 
027 * The fact that you are presently reading this means that you have had
028 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
029 */
030package org.graphstream.stream.file.gexf;
031
032import java.lang.reflect.Array;
033import java.util.HashMap;
034
035import javax.xml.stream.XMLStreamException;
036
037import org.graphstream.stream.SinkAdapter;
038
039public class GEXFNodes extends SinkAdapter implements GEXFElement {
040        GEXF root;
041        HashMap<String, GEXFNode> nodes;
042
043        public GEXFNodes(GEXF root) {
044                this.root = root;
045                this.nodes = new HashMap<String, GEXFNode>();
046
047                root.addSink(this);
048        }
049
050        private float[] convertToXYZ(Object value) {
051                if (value == null || !value.getClass().isArray())
052                        return null;
053
054                float[] xyz = new float[Array.getLength(value)];
055
056                for (int i = 0; i < xyz.length; i++) {
057                        Object o = Array.get(value, i);
058
059                        if (o instanceof Number)
060                                xyz[i] = ((Number) o).floatValue();
061                        else
062                                return null;
063                }
064
065                return xyz;
066        }
067
068        /*
069         * (non-Javadoc)
070         * 
071         * @see
072         * org.graphstream.stream.file.gexf.GEXFElement#export(org.graphstream.stream
073         * .file.gexf.SmartXMLWriter)
074         */
075        public void export(SmartXMLWriter stream) throws XMLStreamException {
076                stream.startElement("nodes");
077
078                for (GEXFNode node : nodes.values())
079                        node.export(stream);
080
081                stream.endElement(); // NODES
082        }
083
084        /*
085         * (non-Javadoc)
086         * 
087         * @see org.graphstream.stream.SinkAdapter#nodeAdded(java.lang.String, long,
088         * java.lang.String)
089         */
090        public void nodeAdded(String sourceId, long timeId, String nodeId) {
091                GEXFNode node = nodes.get(nodeId);
092
093                if (node == null) {
094                        node = new GEXFNode(root, nodeId);
095                        nodes.put(nodeId, node);
096                }
097
098                node.spells.start();
099        }
100
101        /*
102         * (non-Javadoc)
103         * 
104         * @see org.graphstream.stream.SinkAdapter#nodeRemoved(java.lang.String,
105         * long, java.lang.String)
106         */
107        public void nodeRemoved(String sourceId, long timeId, String nodeId) {
108                GEXFNode node = nodes.get(nodeId);
109
110                if (node == null) {
111                        System.err.printf("node removed but not added\n");
112                        return;
113                }
114
115                node.spells.end();
116        }
117
118        /*
119         * (non-Javadoc)
120         * 
121         * @see
122         * org.graphstream.stream.SinkAdapter#nodeAttributeAdded(java.lang.String,
123         * long, java.lang.String, java.lang.String, java.lang.Object)
124         */
125        public void nodeAttributeAdded(String sourceId, long timeId, String nodeId,
126                        String attribute, Object value) {
127                GEXFNode node = nodes.get(nodeId);
128
129                if (("ui.label".equals(attribute) || "label".equals(attribute))
130                                && value != null)
131                        node.label = value.toString();
132
133                if ("xyz".equals(attribute)) {
134                        float[] xyz = convertToXYZ(value);
135
136                        switch (xyz.length) {
137                        default:
138                                node.z = xyz[2];
139                        case 2:
140                                node.y = xyz[1];
141                        case 1:
142                                node.x = xyz[0];
143                        case 0:
144                                break;
145                        }
146
147                        node.position = true;
148                }
149
150                node.attvalues
151                                .attributeUpdated(root.getNodeAttribute(attribute), value);
152        }
153
154        /*
155         * (non-Javadoc)
156         * 
157         * @see
158         * org.graphstream.stream.SinkAdapter#nodeAttributeChanged(java.lang.String,
159         * long, java.lang.String, java.lang.String, java.lang.Object,
160         * java.lang.Object)
161         */
162        public void nodeAttributeChanged(String sourceId, long timeId,
163                        String nodeId, String attribute, Object oldValue, Object newValue) {
164                nodeAttributeAdded(sourceId, timeId, nodeId, attribute, newValue);
165        }
166
167        /*
168         * (non-Javadoc)
169         * 
170         * @see
171         * org.graphstream.stream.SinkAdapter#nodeAttributeRemoved(java.lang.String,
172         * long, java.lang.String, java.lang.String)
173         */
174        public void nodeAttributeRemoved(String sourceId, long timeId,
175                        String nodeId, String attribute) {
176                GEXFNode node = nodes.get(nodeId);
177                node.attvalues.attributeUpdated(root.getNodeAttribute(attribute), null);
178        }
179
180        /*
181         * (non-Javadoc)
182         * 
183         * @see org.graphstream.stream.SinkAdapter#graphCleared(java.lang.String,
184         * long)
185         */
186        public void graphCleared(String sourceId, long timeId) {
187                for (GEXFNode node : nodes.values())
188                        node.spells.end();
189        }
190}