001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/model/coverage/grid/GridCoverageExchange.java $
002 /*---------------- FILE HEADER ------------------------------------------
003
004 This file is part of deegree
005 Copyright (C) 2001-2008 by:
006 EXSE, Department of Geography, University of Bonn
007 http://www.giub.uni-bonn.de/deegree/
008 lat/lon GmbH
009 http://www.lat-lon.de
010
011 This library is free software; you can redistribute it and/or
012 modify it under the terms of the GNU Lesser General Public
013 License as published by the Free Software Foundation; either
014 version 2.1 of the License, or (at your option) any later version.
015
016 This library is distributed in the hope that it will be useful,
017 but WITHOUT ANY WARRANTY; without even the implied warranty of
018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019 Lesser General Public License for more details.
020
021 You should have received a copy of the GNU Lesser General Public
022 License along with this library; if not, write to the Free Software
023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024
025 Contact:
026
027 Andreas Poth
028 lat/lon GmbH
029 Aennchenstr. 19
030 53115 Bonn
031 Germany
032 E-Mail: poth@lat-lon.de
033
034 Klaus Greve
035 Department of Geography
036 University of Bonn
037 Meckenheimer Allee 166
038 53115 Bonn
039 Germany
040 E-Mail: klaus.greve@giub.uni-bonn.de
041
042 ---------------------------------------------------------------------------*/
043 package org.deegree.model.coverage.grid;
044
045 import java.io.IOException;
046 import java.io.InputStream;
047 import java.net.URI;
048 import java.util.ArrayList;
049 import java.util.HashMap;
050 import java.util.List;
051 import java.util.Map;
052
053 import org.deegree.datatypes.CodeList;
054 import org.deegree.datatypes.QualifiedName;
055 import org.deegree.framework.log.ILogger;
056 import org.deegree.framework.log.LoggerFactory;
057 import org.deegree.framework.util.ConvenienceFileFilter;
058 import org.deegree.framework.util.StringTools;
059 import org.deegree.io.shpapi.ShapeFile;
060 import org.deegree.model.crs.CRSFactory;
061 import org.deegree.model.crs.CoordinateSystem;
062 import org.deegree.model.crs.UnknownCRSException;
063 import org.deegree.model.feature.Feature;
064 import org.deegree.model.spatialschema.Envelope;
065 import org.deegree.model.spatialschema.Geometry;
066 import org.deegree.model.spatialschema.GeometryFactory;
067 import org.deegree.ogcbase.CommonNamespaces;
068 import org.deegree.ogcwebservices.InvalidParameterValueException;
069 import org.deegree.ogcwebservices.wcs.configuration.Directory;
070 import org.deegree.ogcwebservices.wcs.configuration.Extension;
071 import org.deegree.ogcwebservices.wcs.configuration.File;
072 import org.deegree.ogcwebservices.wcs.configuration.GridDirectory;
073 import org.deegree.ogcwebservices.wcs.configuration.Shape;
074 import org.deegree.ogcwebservices.wcs.describecoverage.CoverageOffering;
075
076 /**
077 * Support for creation of grid coverages from persistent formats as well as exporting a grid
078 * coverage to a persistent formats. For example, it allows for creation of grid coverages from the
079 * GeoTIFF Well-known binary format and exporting to the GeoTIFF file format. Basic implementations
080 * only require creation of grid coverages from a file format or resource. More sophesticated
081 * implementations may extract the grid coverages from a database. In such case, a
082 * <code>GridCoverageExchange</code> instance will hold a connection to a specific database and
083 * the {@link #dispose} method will need to be invoked in order to close this connection.
084 * <p>
085 *
086 * @author Andreas Poth
087 * @version 1.0
088 * @since 2.0
089 */
090 public class GridCoverageExchange {
091
092 private static final ILogger LOG = LoggerFactory.getLogger( GridCoverageExchange.class );
093
094 private static final URI DEEGREEAPP = CommonNamespaces.buildNSURI( "http://www.deegree.org/app" );
095
096 private static final String APP_PREFIX = "app";
097
098 public static final String SHAPE_IMAGE_FILENAME = "FILENAME";
099
100 public static final String SHAPE_DIR_NAME = "FOLDER";
101
102 private CoverageOffering coverageOffering;
103
104 /**
105 * @param formats
106 */
107 public GridCoverageExchange( CoverageOffering coverageOffering ) {
108 this.coverageOffering = coverageOffering;
109 }
110
111 /**
112 * Returns a grid coverage reader that can manage the specified source
113 *
114 * @param source
115 * An object that specifies somehow the data source. Can be a
116 * {@link java.lang.String}, an {@link java.io.InputStream}, a
117 * {@link java.nio.channels.FileChannel}, whatever. It's up to the associated grid
118 * coverage reader to make meaningful use of it.
119 * @return The grid coverage reader.
120 * @throws IOException
121 * if an error occurs during reading.
122 *
123 * @revisit We need a mechanism to allow the right GridCoverageReader Something like an SPI.
124 * What if we can't find a GridCoverageReader? Do we return null or throw an Exception?
125 */
126 public GridCoverageReader getReader( Object source )
127 throws IOException {
128 if ( !( source instanceof InputStream ) ) {
129 throw new IOException( "source parameter must be an instance of InputStream" );
130 }
131 return null;
132 }
133
134 /**
135 * This method is a deegree specific enhancement of the <tt>GridCoverageExchange</tt>
136 * class/interface as defined by GeoAPI. Returns a grid coverage reader that can manage the
137 * specified source
138 *
139 * @param source
140 * An object that specifies somehow the data source.
141 * @param description
142 * an object describing the grid coverage and the access to avaiable metadata
143 * @param envelope
144 * @param format
145 * @return The grid coverage reader.
146 * @throws IOException
147 * if an error occurs during reading.
148 *
149 * @revisit We need a mechanism to allow the right GridCoverageReader Something like an SPI.
150 * What if we can't find a GridCoverageReader? Do we return null or throw an Exception?
151 */
152 public GridCoverageReader getReader( InputStream source, CoverageOffering description, Envelope envelope,
153 Format format )
154 throws IOException {
155 GridCoverageReader gcr = null;
156 Extension ext = description.getExtension();
157 String type = ext.getType();
158 if ( type.equals( Extension.FILEBASED ) ) {
159 if ( format.getName().toUpperCase().indexOf( "GEOTIFF" ) > -1 ) {
160 gcr = new GeoTIFFGridCoverageReader( source, description, envelope, format );
161 } else if ( isImageFormat( format ) ) {
162 gcr = new ImageGridCoverageReader( source, description, envelope, format );
163 } else {
164 throw new IOException( "not supported file format: " + format.getName() );
165 }
166 } else {
167 throw new IOException( "coverage storage type: " + type
168 + " is not supported with method: getReader(InputStream, "
169 + "CoverageOffering, Envelope, Format )" );
170 }
171 return gcr;
172 }
173
174 /**
175 * This method is a deegree specific enhancement of the <tt>GridCoverageExchange</tt>
176 * class/interface as defined by GeoAPI. Returns a grid coverage reader that can manage the
177 * specified source
178 *
179 * @param resource
180 * a string that specifies somehow the data source (e.g. a file).
181 * @param description
182 * an object describing the grid coverage and the access to avaiable metadata
183 * @param envelope
184 * @param format
185 *
186 * @return The grid coverage reader.
187 * @throws IOException
188 * if an error occurs during reading.
189 *
190 * @revisit We need a mechanism to allow the right GridCoverageReader Something like an SPI.
191 * What if we can't find a GridCoverageReader? Do we return null or throw an Exception?
192 */
193 public GridCoverageReader getReader( Object resource, CoverageOffering description, Envelope envelope, Format format )
194 throws IOException, InvalidParameterValueException {
195 GridCoverageReader gcr = null;
196 Extension ext = description.getExtension();
197 String type = ext.getType();
198 if ( type.equals( Extension.FILEBASED ) ) {
199 File file = new File( null, (String) resource, envelope );
200 if ( format.getName().toUpperCase().indexOf( "GEOTIFF" ) > -1 ) {
201 LOG.logDebug( "creating GeoTIFFGridCoverageReader" );
202 gcr = new GeoTIFFGridCoverageReader( file, description, envelope, format );
203 } else if ( isImageFormat( format ) ) {
204 LOG.logDebug( "creating ImageGridCoverageReader" );
205 gcr = new ImageGridCoverageReader( file, description, envelope, format );
206 } else {
207 throw new IOException( "not supported file format: " + format.getName() );
208 }
209 } else if ( type.equals( Extension.NAMEINDEXED ) ) {
210 LOG.logDebug( "creating nameIndexed CompoundGridCoverageReader" );
211 Directory[] dirs = new Directory[] { (Directory) resource };
212 gcr = getReader( dirs, description, envelope, format );
213 } else if ( type.equals( Extension.SHAPEINDEXED ) ) {
214 LOG.logDebug( "creating shapeIndexed CompoundGridCoverageReader" );
215 File[] files = null;
216 try {
217 files = getFilesFromShape( (Shape) resource, envelope, description );
218 } catch ( UnknownCRSException e ) {
219 throw new InvalidParameterValueException( e );
220 }
221 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
222 for ( int i = 0; i < files.length; i++ ) {
223 LOG.logDebug( "matching tile: ", files[i].getName() );
224 }
225 }
226 gcr = getReader( files, description, envelope, format );
227 } else if ( type.equals( Extension.ORACLEGEORASTER ) ) {
228 LOG.logDebug( "creating OracleGeoRasterGridCoverageReader" );
229 Class clzz;
230 try {
231 clzz = Class.forName( "org.deegree.model.coverage.grid.oracle.GeoRasterReaderAccess" );
232 } catch ( ClassNotFoundException e ) {
233 LOG.logError( e.getMessage(), e );
234 throw new InvalidParameterValueException( e );
235 }
236 GCReaderAccess acc;
237 try {
238 acc = (GCReaderAccess) clzz.newInstance();
239 } catch ( InstantiationException e ) {
240 LOG.logError( e.getMessage(), e );
241 throw new InvalidParameterValueException( e );
242 } catch ( IllegalAccessException e ) {
243 LOG.logError( e.getMessage(), e );
244 throw new InvalidParameterValueException( e );
245 }
246 gcr = acc.createGridCoverageReader( resource, description, envelope, format );
247 } else if ( type.equals( Extension.DATABASEINDEXED ) ) {
248 LOG.logDebug( "creating databaseIndexed CompoundGridCoverageReader" );
249 File[] files = null;
250 try {
251 files = getFilesFromDatabase( (DatabaseIndexedGCMetadata) resource, envelope, description );
252 } catch ( UnknownCRSException e ) {
253 LOG.logError( e.getMessage(), e );
254 throw new InvalidParameterValueException( e );
255 }
256 if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
257 for ( int i = 0; i < files.length; i++ ) {
258 LOG.logDebug( "matching tile: ", files[i].getName() );
259 }
260 }
261 gcr = new CompoundGridCoverageReader( files, description, envelope, format );
262 } else {
263 throw new IOException( "coverage storage type: " + type + " is not supported" );
264 }
265 return gcr;
266 }
267
268 /**
269 * reads the names of the grid coverage files intersecting the requested region from the passed
270 * database.
271 *
272 * @param dbigcmd
273 * @param envelope
274 * @param description
275 * @return file list
276 * @throws UnknownCRSException
277 * @throws InvalidParameterValueException
278 */
279 private File[] getFilesFromDatabase( DatabaseIndexedGCMetadata dbigcmd, Envelope envelope,
280 CoverageOffering description )
281 throws UnknownCRSException, InvalidParameterValueException {
282
283 CoordinateSystem crs = createNativeCRS( description );
284
285 String className = null;
286 if ( dbigcmd.getJDBCConnection().getDriver().toUpperCase().indexOf( "ORACLE" ) > -1 ) {
287 className = DatabaseIndexAccessMessages.getString( "oracle" );
288 } else if ( dbigcmd.getJDBCConnection().getDriver().toUpperCase().indexOf( "POSTGRES" ) > -1 ) {
289 className = DatabaseIndexAccessMessages.getString( "postgres" );
290 }
291 Class clzz;
292 try {
293 clzz = Class.forName( className );
294 } catch ( ClassNotFoundException e ) {
295 LOG.logError( e.getMessage(), e );
296 throw new InvalidParameterValueException( className, e );
297 }
298 DatabaseIndexAccess dbia;
299 try {
300 dbia = (DatabaseIndexAccess) clzz.newInstance();
301 } catch ( InstantiationException e ) {
302 LOG.logError( e.getMessage(), e );
303 throw new InvalidParameterValueException( className, e );
304 } catch ( IllegalAccessException e ) {
305 LOG.logError( e.getMessage(), e );
306 throw new InvalidParameterValueException( className, e );
307 }
308
309 return dbia.getFiles( dbigcmd, envelope, crs );
310 }
311
312 /**
313 * This method is a deegree specific enhancement of the <tt>GridCoverageExchange</tt>
314 * class/interface as defined by GeoAPI. Returns a grid coverage reader that can manage the
315 * specified source
316 *
317 * @param resources
318 * an array strings that specifies somehow the data sources (e.g. some files).
319 * @param description
320 * an object describing the grid coverage and the access to avaiable metadata
321 * @param envelope
322 * @return The grid coverage reader.
323 * @throws IOException
324 * if an error occurs during reading.
325 *
326 * @revisit We need a mechanism to allow the right GridCoverageReader Something like an SPI.
327 * What if we can't find a GridCoverageReader? Do we return null or throw an Exception?
328 */
329 public GridCoverageReader getReader( Object[] resources, CoverageOffering description, Envelope envelope,
330 Format format )
331 throws IOException, InvalidParameterValueException {
332
333 // CS_CoordinateSystem crs = createNativeCRS( description );
334 GridCoverageReader gcr = null;
335 Extension ext = description.getExtension();
336 String type = ext.getType();
337 File[] files = null;
338 if ( type.equals( Extension.FILEBASED ) ) {
339 LOG.logDebug( "creating filebased CompoundGridCoverageReader" );
340 files = (File[]) resources;
341 gcr = new CompoundGridCoverageReader( files, description, envelope, format );
342 } else if ( type.equals( Extension.NAMEINDEXED ) ) {
343 LOG.logDebug( "creating nameIndexed CompoundGridCoverageReader" );
344 try {
345 files = getFilesFromDirectories( (Directory[]) resources, envelope, description );
346 } catch ( UnknownCRSException e ) {
347 throw new InvalidParameterValueException( e );
348 }
349 gcr = new CompoundGridCoverageReader( files, description, envelope, format );
350 } else if ( type.equals( Extension.SHAPEINDEXED ) ) {
351 LOG.logDebug( "creating shapeIndexed CompoundGridCoverageReader" );
352 files = (File[]) resources;
353 gcr = new CompoundGridCoverageReader( files, description, envelope, format );
354 } else if ( type.equals( Extension.ORACLEGEORASTER ) ) {
355 LOG.logDebug( "creating OracleGeoRasterGridCoverageReader" );
356 Class clzz;
357 try {
358 clzz = Class.forName( "org.deegree.model.coverage.grid.oracle.GeoRasterReaderAccess" );
359 } catch ( ClassNotFoundException e ) {
360 LOG.logError( e.getMessage(), e );
361 throw new InvalidParameterValueException( e );
362 }
363 GCReaderAccess acc;
364 try {
365 acc = (GCReaderAccess) clzz.newInstance();
366 } catch ( InstantiationException e ) {
367 LOG.logError( e.getMessage(), e );
368 throw new InvalidParameterValueException( e );
369 } catch ( IllegalAccessException e ) {
370 LOG.logError( e.getMessage(), e );
371 throw new InvalidParameterValueException( e );
372 }
373 gcr = acc.createGridCoverageReader( resources[0], description, envelope, format );
374 } else {
375 throw new IOException( "coverage storage type: " + type + " is not supported" );
376 }
377
378 return gcr;
379 }
380
381 /**
382 * returns true if the passed format is an image format
383 *
384 * @param format
385 * @return <code>true</code> if the passed format is an image format
386 */
387 private boolean isImageFormat( Format format ) {
388 String frmt = format.getName().toUpperCase();
389 return frmt.equalsIgnoreCase( "png" ) || frmt.equalsIgnoreCase( "bmp" ) || frmt.equalsIgnoreCase( "tif" )
390 || frmt.equalsIgnoreCase( "tiff" ) || frmt.equalsIgnoreCase( "gif" ) || frmt.equalsIgnoreCase( "jpg" )
391 || frmt.equalsIgnoreCase( "jpeg" ) || frmt.indexOf( "ECW" ) > -1;
392 }
393
394 /**
395 * reads the names of the grid coverage files intersecting the requested region from the passed
396 * shape (name).
397 *
398 * @param shape
399 * @param envelope
400 * requested envelope
401 * @param description
402 * description (metadata) of the source coverage
403 * @return file list
404 * @throws IOException
405 * @throws UnknownCRSException
406 */
407 private File[] getFilesFromShape( Shape shape, Envelope envelope, CoverageOffering description )
408 throws IOException, UnknownCRSException {
409
410 CoordinateSystem crs = createNativeCRS( description );
411
412 String shapeBaseName = StringTools.replace( shape.getRootFileName(), "\\", "/", true );
413 String shapeDir = shapeBaseName.substring( 0, shapeBaseName.lastIndexOf( "/" ) + 1 );
414
415 ShapeFile shp = new ShapeFile( shapeBaseName );
416 File[] files = null;
417 int[] idx = shp.getGeoNumbersByRect( envelope );
418 if ( idx != null ) {
419 files = new File[idx.length];
420 try {
421 for ( int i = 0; i < files.length; i++ ) {
422 Feature feature = shp.getFeatureByRecNo( idx[i] );
423 QualifiedName qn = new QualifiedName( APP_PREFIX, SHAPE_IMAGE_FILENAME, DEEGREEAPP );
424 String img = (String) feature.getDefaultProperty( qn ).getValue();
425 qn = new QualifiedName( APP_PREFIX, SHAPE_DIR_NAME, DEEGREEAPP );
426 String dir = (String) feature.getDefaultProperty( qn ).getValue();
427 if ( !( new java.io.File( dir ).isAbsolute() ) ) {
428 // solve relative path; it is assumed that the tile directories
429 // are located in the same directory as the shape file
430 dir = shapeDir + dir;
431 }
432 Geometry geom = feature.getGeometryPropertyValues()[0];
433 Envelope env = geom.getEnvelope();
434 env = GeometryFactory.createEnvelope( env.getMin(), env.getMax(), crs );
435 files[i] = new File( crs, dir.concat( "/".concat( img ) ), env );
436 }
437 } catch ( Exception e ) {
438 shp.close();
439 LOG.logError( e.getMessage(), e );
440 throw new IOException( e.getMessage() );
441 }
442 } else {
443 files = new File[0];
444 }
445 shp.close();
446
447 return files;
448
449 }
450
451 /**
452 * reads the names of the grid coverage files intersecting the requested region from raster data
453 * files contained in the passed directories
454 *
455 * @param directories
456 * list of directories searched for matching raster files
457 * @param envelope
458 * requested envelope
459 * @param description
460 * description (metadata) of the source coverage
461 * @return list of files intersecting the requested envelope
462 * @throws UnknownCRSException
463 * @throws IOException
464 */
465 private File[] getFilesFromDirectories( Directory[] directories, Envelope envelope, CoverageOffering description )
466 throws UnknownCRSException {
467
468 CoordinateSystem crs = createNativeCRS( description );
469
470 List<File> list = new ArrayList<File>( 1000 );
471
472 for ( int i = 0; i < directories.length; i++ ) {
473
474 double widthCRS = ( (GridDirectory) directories[i] ).getTileWidth();
475 double heightCRS = ( (GridDirectory) directories[i] ).getTileHeight();
476 String[] extensions = directories[i].getFileExtensions();
477 String dirName = directories[i].getName();
478
479 ConvenienceFileFilter fileFilter = new ConvenienceFileFilter( false, extensions );
480 java.io.File iofile = new java.io.File( dirName );
481 String[] tiles = iofile.list( fileFilter );
482 for ( int j = 0; j < tiles.length; j++ ) {
483 int pos1 = tiles[j].indexOf( '_' );
484 int pos2 = tiles[j].lastIndexOf( '.' );
485 String tmp = tiles[j].substring( 0, pos1 );
486 double x1 = Double.parseDouble( tmp ) / 1000d;
487 tmp = tiles[j].substring( pos1 + 1, pos2 );
488 double y1 = Double.parseDouble( tmp ) / 1000d;
489 Envelope env = GeometryFactory.createEnvelope( x1, y1, x1 + widthCRS, y1 + heightCRS, crs );
490 if ( env.intersects( envelope ) ) {
491 File file = new File( crs, dirName + '/' + tiles[j], env );
492 list.add( file );
493 }
494 }
495
496 }
497
498 File[] files = list.toArray( new File[list.size()] );
499
500 return files;
501 }
502
503 /**
504 * creates an instance of <tt>CS_CoordinateSystem</tt> from the name of the native CRS of the
505 * grid coverage
506 *
507 * @param description
508 * @return
509 * @throws UnknownCRSException
510 */
511 private CoordinateSystem createNativeCRS( CoverageOffering description )
512 throws UnknownCRSException {
513 String srs = description.getSupportedCRSs().getNativeSRSs()[0].getCodes()[0];
514
515 return CRSFactory.create( srs );
516 }
517
518 /**
519 * Returns a GridCoverageWriter that can write the specified format. The file format name is
520 * determined from the {@link Format} interface. Sample file formats include:
521 *
522 * <blockquote><table>
523 * <tr>
524 * <td>"GeoTIFF"</td>
525 * <td> - GeoTIFF</td>
526 * </tr>
527 * <tr>
528 * <td>"PIX"</td>
529 * <td> - PCI Geomatics PIX</td>
530 * </tr>
531 * <tr>
532 * <td>"HDF-EOS"</td>
533 * <td> - NASA HDF-EOS</td>
534 * </tr>
535 * <tr>
536 * <td>"NITF"</td>
537 * <td> - National Image Transfer Format</td>
538 * </tr>
539 * <tr>
540 * <td>"STDS-DEM"</td>
541 * <td> - Standard Transfer Data Standard</td>
542 * </tr>
543 * </table></blockquote>
544 *
545 * @param destination
546 * An object that specifies somehow the data destination. Can be a
547 * {@link java.lang.String}, an {@link java.io.OutputStream}, a
548 * {@link java.nio.channels.FileChannel}, whatever. It's up to the associated grid
549 * coverage writer to make meaningful use of it.
550 * @param format
551 * the output format.
552 * @return The grid coverage writer.
553 * @throws IOException
554 * if an error occurs during reading.
555 */
556 public GridCoverageWriter getWriter( Object destination, Format format )
557 throws IOException {
558
559 LOG.logDebug( "requested format: ", format.getName() );
560
561 GridCoverageWriter gcw = null;
562
563 if ( !isKnownFormat( format ) ) {
564 throw new IOException( "not supported Format: " + format );
565 }
566
567 Map<String, Object> metadata = new HashMap<String, Object>();
568 metadata.put( "offset", coverageOffering.getExtension().getOffset() );
569 metadata.put( "scaleFactor", coverageOffering.getExtension().getScaleFactor() );
570 if ( format.getName().equalsIgnoreCase( "GEOTIFF" ) ) {
571 gcw = new GeoTIFFGridCoverageWriter( destination, metadata, null, null, format );
572 } else if ( isImageFormat( format ) ) {
573 gcw = new ImageGridCoverageWriter( destination, metadata, null, null, format );
574 } else if ( format.getName().equalsIgnoreCase( "GML" ) || format.getName().equalsIgnoreCase( "GML2" )
575 || format.getName().equalsIgnoreCase( "GML3" ) ) {
576 gcw = new GMLGridCoverageWriter( destination, metadata, null, null, format );
577 } else if ( format.getName().equalsIgnoreCase( "XYZ" ) ) {
578 gcw = new XYZGridCoverageWriter( destination, metadata, null, null, format );
579 } else {
580 throw new IOException( "not supported Format: " + format );
581 }
582
583 return gcw;
584 }
585
586 /**
587 * validates if a passed format is known to an instance of <tt>GridCoverageExchange</tt>
588 *
589 * @param format
590 * @return <code>true</code> if the format is known, <code>false</code> otherwise.
591 */
592 private boolean isKnownFormat( Format format ) {
593 CodeList[] codeList = coverageOffering.getSupportedFormats().getFormats();
594 for ( int i = 0; i < codeList.length; i++ ) {
595 String[] codes = codeList[i].getCodes();
596 for ( int j = 0; j < codes.length; j++ ) {
597 if ( format.getName().equalsIgnoreCase( codes[j] ) ) {
598 return true;
599 }
600 }
601 }
602 LOG.logDebug( format.getName() + " not supported" );
603 return false;
604 }
605
606 }