001/*-
002 * Copyright 2015, 2016 Diamond Light Source Ltd.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 */
009
010package org.eclipse.january.dataset;
011
012import java.util.Arrays;
013import java.util.EventObject;
014import java.util.regex.Matcher;
015import java.util.regex.Pattern;
016
017/**
018 * Event fired to diseminate information about a dataset changing.
019 * For instance if an image represents a live stream.
020 * 
021 * This event is passed over web-sockets. To keep dependencies to a 
022 * minimum and since it is really simple, we have added an encode and
023 * decode to JSON without the need for an API like jackson.
024 */
025public class DataEvent extends EventObject {
026        
027        /**
028         * 
029         */
030        private static final long serialVersionUID = 751125872769278449L;
031
032        private int[]  shape;
033        
034        /**
035         * Optionally, we can indicate where the file path was.
036         */
037        private String filePath;
038
039        /**
040         * The name of the dataset, may be ""
041         */
042        private String name;
043
044        public DataEvent() {
045                this("", new int[]{1});
046        }
047
048        /**
049         * Creates an event to notify that this data has changed.
050         * @param name
051         */
052        public DataEvent(String name, int[] shape) {
053                super(name);
054                this.shape = shape;
055                this.name  = name;
056        }
057
058        @Override
059        public String getSource() {
060                return (String)super.getSource();
061        }
062        
063        public String getName() {
064                return getSource();
065        }
066        
067        public void setName(String name) {
068                this.name = name;
069        }
070        
071        public int[] getShape() {
072                return shape;
073        }
074
075        public void setShape(int[] shape) {
076                this.shape = shape;
077        }
078
079        public String getFilePath() {
080                return filePath;
081        }
082
083        public void setFilePath(String filePath) {
084                this.filePath = filePath;
085        }
086
087        /**
088         * Encodes event to string
089         * @return encoded string
090         */
091        public String encode() {
092                final StringBuilder buf = new StringBuilder();
093                buf.append("{");
094                buf.append("\"name\" : \"");
095                buf.append(getName());
096                buf.append("\"");
097                buf.append(", \"shape\" : ");
098                buf.append(Arrays.toString(shape));
099                
100                buf.append(", \"filepath\" : \"");
101                buf.append(getFilePath());
102                buf.append("\"");
103                
104                buf.append("}");
105                return buf.toString();
106        }
107        
108        /**
109         * Decodes from String for instance {"name" : "Tests", "shape" : [1024, 1024], "filepath" : "C:/tmp/Fred.txt"}
110         * @return DataEvent
111         */
112        public static DataEvent decode(String json) {
113                
114                String name     = getValue(json, ".*\"name\" \\: \"([^\"]+)\".*");
115                String filepath = getValue(json, ".*\"filepath\" \\: \"([^\"]+)\".*");
116                String shape    = getValue(json, ".*\"shape\" \\: \\[([^\\]]+)\\].*");
117
118                DataEvent ret = new DataEvent(name, getArray(shape));
119                if (filepath!=null && !"null".equals(filepath)) {
120                        ret.setFilePath(filepath);
121                }
122                return ret;
123        }
124
125
126        private static String getValue(String json, String regex) {
127                Matcher matcher = Pattern.compile(regex).matcher(json);
128                if (matcher.matches()) {
129                        return matcher.group(1);
130                }
131                throw new RuntimeException(regex+" unmatched in "+json);
132        }
133
134        private static int[] getArray(String value) {
135                String[] split = value.split(",");
136                int[] ret      = new int[split.length];
137                for (int i = 0; i < split.length; i++) ret[i] = Integer.parseInt(split[i].trim());
138                return ret;
139        }
140
141        @Override
142        public int hashCode() {
143                final int prime = 31;
144                int result = 1;
145                result = prime * result + ((filePath == null) ? 0 : filePath.hashCode());
146                result = prime * result + ((name == null) ? 0 : name.hashCode());
147                result = prime * result + Arrays.hashCode(shape);
148                return result;
149        }
150
151        @Override
152        public boolean equals(Object obj) {
153                if (this == obj)
154                        return true;
155                if (obj == null)
156                        return false;
157                if (getClass() != obj.getClass())
158                        return false;
159                DataEvent other = (DataEvent) obj;
160                if (filePath == null) {
161                        if (other.filePath != null)
162                                return false;
163                } else if (!filePath.equals(other.filePath))
164                        return false;
165                if (name == null) {
166                        if (other.name != null)
167                                return false;
168                } else if (!name.equals(other.name))
169                        return false;
170                if (!Arrays.equals(shape, other.shape))
171                        return false;
172                return true;
173        }
174
175}