001/*
002 * Copyright (c) 2014-2015 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2018-09-06 23:18:45 +0000 (Thu, 06 Sep 2018) $' 
007 * '$Revision: 34709 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029package org.kepler.gis.data;
030
031import java.io.IOException;
032import java.io.Serializable;
033
034import org.geotools.data.simple.SimpleFeatureCollection;
035import org.geotools.data.simple.SimpleFeatureSource;
036import org.kepler.gis.util.VectorUtilities;
037import org.opengis.filter.Filter;
038import org.opengis.referencing.crs.CoordinateReferenceSystem;
039
040import ptolemy.data.BooleanToken;
041import ptolemy.data.Token;
042import ptolemy.data.type.Type;
043import ptolemy.kernel.util.IllegalActionException;
044
045/** Token containing GIS vectors.
046 * 
047 *  @author Daniel Crawl
048 *  @version $Id: VectorToken.java 34709 2018-09-06 23:18:45Z crawl $
049 *  
050 */
051public class VectorToken extends Token {
052
053    /** Create a new VectorToken from a set of features. */
054    public VectorToken(SimpleFeatureCollection features) throws IllegalActionException {
055        
056        if(features == null) {// || features.isEmpty()) {
057            //throw new IllegalActionException("Cannot create VectorToken with empty features.");
058            throw new IllegalActionException("Cannot create VectorToken with null features.");
059        }
060        
061        _features = features;
062    }
063    
064    /** Create a new VectorToken from a feature source.
065     *  @param source A data source for the features.
066     *  @param defaultCRS Coordinate reference system to use if not defined by the source.
067     */
068    public VectorToken(SimpleFeatureSource source, CoordinateReferenceSystem defaultCRS) {
069        _source = source;
070        _defaultCRS = defaultCRS;
071    }
072    
073    public VectorToken(String string) {
074        // TODO
075    }
076
077    /** Get the set of features represented in this token.
078     * NOTE: if you need to modify the features, make a copy first.
079     */
080    public SimpleFeatureCollection getVectors() throws IllegalActionException {
081        if(_source != null) {
082            try {
083                SimpleFeatureCollection features = _source.getFeatures();
084                if(_defaultCRS != null &&
085                    features.getSchema().getCoordinateReferenceSystem() == null) {
086                    features = VectorUtilities.setCRS(features, _defaultCRS);
087                }
088                return features;
089            } catch (IOException e) {
090                throw new IllegalActionException("Error reading features " +
091                    "from data source: " + e.getMessage());
092            }
093        } else {
094            return _features;
095        }
096    }
097    
098    /** Get the filtered set of features represented in this token.
099     *  NOTE: if you need to modify the features, make a copy first.
100     *  @param filter A filter to select a subset of the features. 
101     */
102    public SimpleFeatureCollection getFilteredVectors(Filter filter) throws IllegalActionException {
103        if(_features != null) {
104            return _features.subCollection(filter);
105        } else {
106            try {
107                SimpleFeatureCollection features = _source.getFeatures(filter);
108                if(_defaultCRS != null &&
109                    features.getSchema().getCoordinateReferenceSystem() == null) {
110                    features = VectorUtilities.setCRS(features, _defaultCRS);
111                }
112                return features;
113            } catch (IOException e) {
114                throw new IllegalActionException("Error reading features " +
115                    "from data source: " + e.getMessage());
116            }
117        }
118    }
119    
120    /** Get the token type. */
121    @Override
122    public Type getType() {
123        return VECTOR;
124    }
125    
126    /**
127     * Test for equality of the values of this Token and the argument Token. If
128     * the value of this token or the value of the rightArgument token is null,
129     * then we return False.
130     * 
131     * @param rightArgument
132     *            The Token to test against.
133     * @exception IllegalActionException
134     *                Not thrown in this base class.
135     * @return A boolean token that contains the value true if the dates are the
136     *         same.
137     */
138    @Override
139    public final BooleanToken isEqualTo(Token rightArgument)
140            throws IllegalActionException {
141        
142        // FIXME this does not consider _source
143        SimpleFeatureCollection rightData = ((VectorToken) rightArgument).getVectors();
144        SimpleFeatureCollection leftData = getVectors();
145
146        if ((rightData == null) || (leftData == null)) {
147            return BooleanToken.FALSE;
148        } else if (rightData == leftData) {
149            return BooleanToken.TRUE;
150        } else {
151            return BooleanToken.FALSE;
152        }
153    }
154
155    /** Return a String representation of the VectorToken. */
156    @Override
157    public String toString() {
158        if(_source != null) {
159            return _source.toString();
160        } else if (_features == null) {
161            return "";
162        } else {
163            return _features.toString();
164        }
165    }
166    
167    public static class VectorType implements Cloneable, Type, Serializable {
168
169        @Override
170        public Type add(Type rightArgumentType) {
171            // TODO Auto-generated method stub
172            return this;
173        }
174
175        @Override
176        public Object clone() {
177            return this;
178        }
179        
180        @Override
181        public Token convert(Token token) throws IllegalActionException {
182            if (token instanceof VectorToken) {
183                return token;
184            } else {
185                throw new IllegalActionException("Attempt to convert token "
186                        + token + " into a Vector token, which is not possible.");
187            }
188        }
189
190        @Override
191        public Type divide(Type rightArgumentType) {
192            // TODO Auto-generated method stub
193            return this;
194        }
195
196        @Override
197        public int getTypeHash() {
198            // TODO Auto-generated method stub
199            return 0;
200        }
201
202        @Override
203        public Class<?> getTokenClass() {
204            return VectorToken.class;
205        }
206
207        @Override
208        public boolean isAbstract() {
209            return false;
210        }
211
212        @Override
213        public boolean isCompatible(Type type) {
214            return type == this;
215        }
216
217        @Override
218        public boolean isConstant() {
219            return true;
220        }
221
222        @Override
223        public boolean isInstantiable() {
224            return true;
225        }
226
227        @Override
228        public boolean isSubstitutionInstance(Type type) {
229            return type == this;
230        }
231
232        @Override
233        public Type modulo(Type rightArgumentType) {
234            // TODO Auto-generated method stub
235            return this;
236        }
237
238        @Override
239        public Type multiply(Type rightArgumentType) {
240            // TODO Auto-generated method stub
241            return this;
242        }
243
244        @Override
245        public Type one() {
246            // TODO Auto-generated method stub
247            return this;
248        }
249
250        @Override
251        public Type subtract(Type rightArgumentType) {
252            // TODO Auto-generated method stub
253            return this;
254        }
255
256        @Override
257        public String toString() {
258            return "vector";
259        }
260        
261        @Override
262        public Type zero() {
263            // TODO Auto-generated method stub
264            return this;
265        }
266
267    }
268    
269    public static final VectorType VECTOR = new VectorType();
270
271    private SimpleFeatureCollection _features;
272    private SimpleFeatureSource _source;
273    
274    /** Coordinate reference system to use if not defined by the SimpleFeatureSource. */
275    private CoordinateReferenceSystem _defaultCRS;
276}