001/*
002 *   AbstractGeomReader -- A partial implementation of the GeomReader interface.
003 *
004 *   Copyright (C) 2010-2015, Joseph A. Huwaldt
005 *   All rights reserved.
006 *   
007 *   This library is free software; you can redistribute it and/or
008 *   modify it under the terms of the GNU Lesser General Public
009 *   License as published by the Free Software Foundation; either
010 *   version 2.1 of the License, or (at your option) any later version.
011 *   
012 *   This library is distributed in the hope that it will be useful,
013 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
014 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015 *   Lesser General Public License for more details.
016 *
017 *   You should have received a copy of the GNU Lesser General Public License
018 *   along with this program; if not, write to the Free Software
019 *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
020 *   Or visit:  http://www.gnu.org/licenses/lgpl.html
021 */
022package geomss.geom.reader;
023
024import geomss.geom.GeomUtil;
025import geomss.geom.GeometryList;
026import geomss.geom.PointVehicle;
027import java.io.File;
028import java.io.IOException;
029import java.io.LineNumberReader;
030import java.text.MessageFormat;
031import java.util.List;
032import static java.util.Objects.isNull;
033import java.util.ResourceBundle;
034import javax.measure.quantity.Length;
035import javax.measure.unit.Unit;
036import javolution.util.FastTable;
037
038/**
039 * A partial implementation of the {@link GeomReader} interface. Some methods have default
040 * implementations that sub-classes should override as needed.
041 * 
042 * <p> Modified by: Joseph A. Huwaldt </p>
043 * 
044 * @author Joseph A. Huwaldt, Date: August 26, 2010
045 * @version November 28, 2015
046 */
047public abstract class AbstractGeomReader implements GeomReader {
048
049    /**
050     * The resource bundle for this package.
051     */
052    protected static final ResourceBundle RESOURCES
053            = ResourceBundle.getBundle("geomss.geom.reader.GeomReaderResources",
054                    java.util.Locale.getDefault());
055
056    /**
057     * A list of any warning messages from the reader.
058     */
059    protected List<String> _warnings = FastTable.newInstance();
060
061    // The units used for the geometry in the specified file.
062    private Unit<Length> _units = GeomUtil.getDefaultUnit();
063
064    /**
065     * Read a line from the given reader and throw an exception of EOF is encountered.
066     *
067     * @param reader The LineNumberReader to read from.
068     * @return The line read from the reader.
069     * @throws IOException if EOF was encountered.
070     */
071    protected static final String readLine(LineNumberReader reader) throws IOException {
072        String data = reader.readLine();
073         if (isNull(data))
074            throw new IOException(
075                    MessageFormat.format(RESOURCES.getString("EOFMsg"), reader.getLineNumber()));
076        return data;
077    }
078    
079    /**
080     * Compares this object with the specified object for order based on the
081     * <code>toString().compareTo(o.toString())</code> method. Returns a negative integer,
082     * zero, or a positive integer as this object is less than, equal to, or greater than
083     * the specified object.
084     */
085    @Override
086    public int compareTo(Object o) {
087        return this.toString().compareTo(o.toString());
088    }
089
090    /**
091     * Method that determines if this reader can read geometry from the specified input
092     * file. This implementation always returns NO.
093     *
094     * @param inputFile The input file containing the geometry to be read in.
095     * @return GeomReader.YES if this class can definitely read the file, GeomReader.MAYBE
096     *         if the file could possibly be read and GeomReader.NO if the file can
097     *         definitely not be read by this class.
098     * @throws java.io.IOException Could be thrown by sub-classes and indicates that the
099     * file can not be read by this reader.
100     */
101    @Override
102    public int canReadData(File inputFile) throws IOException {
103        return NO;
104    }
105
106    /**
107     * Returns <code>true</code> if this class can write at least some data in the format
108     * supported by this class. Returns <code>false</code> if it can not.
109     * <p>
110     * This default implementation always returns false.
111     * </p>
112     *
113     * @return true if this class can write at least some data in the format supported by
114     *         this class.
115     */
116    @Override
117    public boolean canWriteData() {
118        return false;
119    }
120
121    /**
122     * Reads in a geometry file from the supplied input file and returns a
123     * {@link GeometryList} object that contains the geometry from the file.
124     * <p>
125     * WARNING! This method must be implemented by sub-classes and  this implementation
126     * will throw an exception if you try and use it.
127     * </p>
128     *
129     * @param inputFile The input file containing the geometry to be read in.
130     * @return A {@link GeometryList} object containing the geometry read in from the
131     *         file.
132     * @throws IOException If there is a problem reading the specified file.
133     * @see #setFileUnits(javax.measure.unit.Unit) 
134     */
135    @Override
136    public GeometryList read(File inputFile) throws IOException {
137        throw new IOException(
138                MessageFormat.format(RESOURCES.getString("unsupportedReadMsg"), toString()));
139    }
140
141    /**
142     * Return a list of any warning messages that the reader/writer may have issued.
143     *
144     * @return A list of any warning messages that the reader/writer may have issued.
145     */
146    @Override
147    public List<String> getWarnings() {
148        FastTable<String> output = FastTable.newInstance();
149        output.addAll(_warnings);
150        return output;
151    }
152
153    /**
154     * Writes out a geometry file for the geometry contained in the supplied
155     * {@link GeometryList} object.
156     * <p>
157     * WARNING! This method must be implemented by sub-classes and  this implementation
158     * will throw an exception if you try and use it.
159     * </p>
160     *
161     * @param outputFile The output File to which the geometry is to be written.
162     * @param geometry   The {@link GeometryList} object containing the geometry to be
163     *                   written out.
164     * @throws IOException If there is a problem writing to the specified file.
165     */
166    @Override
167    public void write(File outputFile, GeometryList geometry) throws IOException {
168        throw new IOException(
169                MessageFormat.format(RESOURCES.getString("unsupportedWriteMsg"), toString()));
170    }
171
172    /**
173     * Sets the units used for the geometry as stored in a non-unit aware geometry file
174     * being read in. The geometry is returned in these units for file types which are not
175     * unit aware. If the file format specifies units, the input from this method will be
176     * ignored. If this method is not called before reading a non-unit aware geometry
177     * file, then the units of the returned geometry will be the system default units.
178     * When writing out geometry, this is ignored.
179     *
180     * @param units The units used for the geometry in the file being read in. If null is
181     *              passed, the units will default to the default system units.
182     * @see #isUnitAware() 
183     */
184    @Override
185    public void setFileUnits(Unit<Length> units) {
186        if (units == null)
187            units = GeomUtil.getDefaultUnit();
188        _units = units;
189    }
190
191    /**
192     * Returns the units used for the geometry when reading a file format that is
193     * not unit aware. This is ignored for readers that are unit aware.
194     *
195     * @return The units used for the geometry when reading a file format that is
196     *         not unit aware.
197     */
198    protected Unit<Length> getFileUnits() {
199        return _units;
200    }
201
202    /**
203     * Convert a generic GeometryList into a PointVehicle. If the input GeometryList is a
204     * PointVehicle, it is simply returned. If the input GeometryList contains anything
205     * other than PointComponent objects, an exception is thrown. If the input geomList is
206     * <code>null</code>, then <code>null</code> is returned. Otherwise a new PointVehicle
207     * is created containing the PointComponent objects in the input list. It's name is
208     * also set to the name of the input list.
209     *
210     * @param geomList The GeometryList to convert into a PointVehicle list if possible.
211     * @return The input GeometryList converted into a PointVehicle list.
212     * @throws java.io.IOException If the input GeometryList could not be converted into a
213     * PointVehicle list.
214     */
215    protected static PointVehicle geomList2PointVehicle(GeometryList geomList) throws IOException {
216        if (geomList == null)
217            return null;
218
219        PointVehicle vehicle;
220        if (geomList instanceof PointVehicle)
221            vehicle = (PointVehicle)geomList;
222        else {
223            try {
224                vehicle = PointVehicle.newInstance();
225                vehicle.addAll(geomList);
226                vehicle.setName(geomList.getName());
227            } catch (Exception e) {
228                throw new IOException(RESOURCES.getString("inputNotListOfComponents"));
229            }
230        }
231
232        return vehicle;
233    }
234}