/* * Licensed Materials - Property of Perforce Software, Inc. * © Copyright Perforce Software, Inc. 2014, 2021 * © Copyright IBM Corp. 2009, 2014 * © Copyright ILOG 1996, 2009 * All Rights Reserved. * * Note to U.S. Government Users Restricted Rights: * The Software and Documentation were developed at private expense and * are "Commercial Items" as that term is defined at 48 CFR 2.101, * consisting of "Commercial Computer Software" and * "Commercial Computer Software Documentation", as such terms are * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4, * as applicable. */ package ilog.views.maps.format.fme; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import COM.safe.fmeobjects.FMEException; import COM.safe.fmeobjects.FMEFormatInfo; import COM.safe.fmeobjects.FMEObjects; import COM.safe.fmeobjects.IFMEFeature; import COM.safe.fmeobjects.IFMEFeatureVector; import COM.safe.fmeobjects.IFMESession; import COM.safe.fmeobjects.IFMEStringArray; import COM.safe.fmeobjects.IFMEUniversalReader; import ilog.views.maps.IlvAttributeInfoProperty; import ilog.views.maps.IlvCoordinate; import ilog.views.maps.IlvFeatureAttribute; import ilog.views.maps.IlvFeatureAttributeProperty; import ilog.views.maps.IlvMapFeature; import ilog.views.maps.IlvMapGeometry; import ilog.views.maps.attribute.IlvStringAttribute; import ilog.views.maps.geometry.IlvMapGeometryCollection; import ilog.views.maps.geometry.IlvMapLineString; import ilog.views.maps.geometry.IlvMapMultiPoint; import ilog.views.maps.geometry.IlvMapPolygon; import ilog.views.maps.geometry.IlvMapSegmentRing; import ilog.views.maps.geometry.IlvMapText; import ilog.views.maps.srs.coordsys.IlvCoordinateSystem; import ilog.views.maps.srs.wkt.IlvWKTCoordinateSystemFactory; /** * FME Objects reader. */ public class FMEDataset { // fme_type static final private String kFME_Type = "fme_type"; //$NON-NLS-1$ // static final private String kFME_No_Geom = "fme_no_geom"; //$NON-NLS-1$ static final private String kFME_Point = "fme_point"; //$NON-NLS-1$ // static final private String kFME_Line = "fme_line"; //$NON-NLS-1$ // static final private String kFME_Area = "fme_area"; //$NON-NLS-1$ static final private String kFME_Text = "fme_text"; //$NON-NLS-1$ static final private String kFME_Ellipse = "fme_ellipse"; //$NON-NLS-1$ static final private String kFME_Arc = "fme_arc"; //$NON-NLS-1$ static final private String kFME_Raster = "fme_raster"; //$NON-NLS-1$ // static final private String kFME_Undefined = "fme_undefined"; //$NON-NLS-1$ // Arc, ellipse, text attributes static final private String kFME_Rotation = "fme_rotation"; //$NON-NLS-1$ static final private String kFME_Primary_Axis = "fme_primary_axis"; //$NON-NLS-1$ static final private String kFME_Secondary_Axis = "fme_secondary_axis"; //$NON-NLS-1$ static final private String kFME_Start_Angle = "fme_start_angle"; //$NON-NLS-1$ static final private String kFME_Sweep_Angle = "fme_sweep_angle"; //$NON-NLS-1$ static final private String kFME_Text_String = "fme_text_string"; //$NON-NLS-1$ // static final private String kFME_Text_Size = "fme_text_size"; //$NON-NLS-1$ private IFMESession fmeSession; private IFMEUniversalReader fmeReader; private Hashtable<String, IlvAttributeInfoProperty> fmeAttributeInfoProperties = new Hashtable<String, IlvAttributeInfoProperty>(); /** * Creates a new <code>FMEDataset</code>. * * @throws FMEException */ FMEDataset() throws FMEException { fmeSession = FMEObjects.createSession(); IFMEStringArray fmeDirectives = fmeSession.createStringArray(); fmeSession.init(fmeDirectives); fmeDirectives.dispose(); } /** * @see java.lang.Object#finalize() */ public void dispose() { // Make that we don't leave an open reader behind. try { closeReader(); } catch (FMEException e) { // Handle the exception here since this method will be called from // within catch() blocks. new Exception(e.getMessage() + " " + e.getErrorNumber() + " " + e.getFMEStackTrace()).printStackTrace(); //$NON-NLS-1$//$NON-NLS-2$ } finally { // Free all the FME Objects resources. fmeSession.dispose(); fmeSession = null; } } Override protected void finalize() { dispose(); } /** * Opens the FME dataset. * * @param format * A valid FME Format. * @param fileName * The file name. * @throws FMEException */ public void open(String format, String fileName) throws FMEException { closeReader(); FMEFormatInfo datasetInfo = new FMEFormatInfo(format, fileName); IFMEStringArray fmeDirectives = fmeSession.createStringArray(); fmeReader = fmeSession.createReader(datasetInfo.format, true, fmeDirectives); fmeDirectives.dispose(); IFMEStringArray fmeParameters = fmeSession.createStringArray(); fmeReader.open(datasetInfo.dataset, fmeParameters); fmeParameters.dispose(); } private void closeReader() throws FMEException { // Close the reader if it's open. if (fmeReader != null) { fmeReader.close(); fmeReader.dispose(); fmeReader = null; } fmeAttributeInfoProperties.clear(); } /** * Reads the FME Schema and returns the list of layer names. * * @return Returns the list of layer names. * @throws FMEException */ public String[] readLayerList() throws FMEException { List<String> layers = new ArrayList<String>(); // Get the schema features from the reader. IFMEFeature feature = fmeSession.createFeature(); while (fmeReader.readSchema(feature)) { layers.add(feature.getFeatureType()); } feature.dispose(); return layers.toArray(new String[0]); } // This function extracts the coordinate geometry of the features for // later use in drawing the features when a feature is selected. private IlvMapGeometry getFeatureCoords(IFMEFeature feature) throws FMEException { String strFme_Type = feature.getStringAttribute(kFME_Type); switch (feature.getGeometryType()) { case IFMEFeature.FME_GEOM_POINT: if (strFme_Type.compareTo(kFME_Text) == 0) { return getTextCoords(feature); } else if (strFme_Type.compareTo(kFME_Point) == 0) { return getPointCoords(feature); } else if (strFme_Type.compareTo(kFME_Arc) == 0 || strFme_Type.compareTo(kFME_Ellipse) == 0) { return getArcCoords(feature); } else { System.err.println("Invalid fme_type."); //$NON-NLS-1$ } break; case IFMEFeature.FME_GEOM_LINE: return getSimpleCoords(feature); case IFMEFeature.FME_GEOM_POLYGON: if (strFme_Type.compareTo(kFME_Raster) == 0) { ArrayList<String> attributeNames = new ArrayList<String>(); feature.getAllAttributeNames(attributeNames); return new IlvMapPolygon(new IlvMapSegmentRing(getSimpleCoords(feature))); } return new IlvMapPolygon(new IlvMapSegmentRing(getSimpleCoords(feature))); case IFMEFeature.FME_GEOM_DONUT: return getDonutCoords(feature); case IFMEFeature.FME_GEOM_AGGREGATE: return getAggregateCoords(feature); case IFMEFeature.FME_GEOM_UNDEFINED: break; case IFMEFeature.FME_GEOM_PIP: default: System.err.println("Invalid fme_geometry."); //$NON-NLS-1$ } return null; } private IlvMapLineString getSimpleCoords(IFMEFeature feature) { IlvMapLineString primitivePointList = new IlvMapLineString(); for (int i = 0; i < feature.numCoords(); i++) { IlvCoordinate c = new IlvCoordinate(feature.getXCoordinate(i), feature.getYCoordinate(i)); primitivePointList.addPoint(c); } return primitivePointList; } private IlvMapMultiPoint getPointCoords(IFMEFeature feature) { IlvMapMultiPoint primitivePointList = new IlvMapMultiPoint(); for (int i = 0; i < feature.numCoords(); i++) { IlvCoordinate c = new IlvCoordinate(feature.getXCoordinate(i), feature.getYCoordinate(i)); primitivePointList.addPoint(c); } return primitivePointList; } private IlvMapText getTextCoords(IFMEFeature feature) throws FMEException { String str = feature.getStringAttribute(kFME_Text_String); IlvCoordinate c = new IlvCoordinate(feature.getXCoordinate(0), feature.getYCoordinate(0)); return new IlvMapText(c, str); } private IlvMapLineString getArcCoords(IFMEFeature feature) throws FMEException { double centerX = feature.getXCoordinate(0); double centerY = feature.getYCoordinate(0); double rotation = feature.getDoubleAttribute(kFME_Rotation); double primaryAxis = feature.getDoubleAttribute(kFME_Primary_Axis); double secondaryAxis = feature.getDoubleAttribute(kFME_Secondary_Axis); double startAngle = 0; double sweepAngle = 360; double endAngle = 360; String strFme_Type = feature.getStringAttribute(kFME_Type); if (strFme_Type.compareTo(kFME_Arc) == 0) { startAngle = feature.getDoubleAttribute(kFME_Start_Angle); sweepAngle = feature.getDoubleAttribute(kFME_Sweep_Angle); endAngle = startAngle + sweepAngle; } feature.convertArcToPoints(centerX, centerY, primaryAxis, secondaryAxis, 0, startAngle, endAngle, rotation); return getSimpleCoords(feature); } private IlvMapPolygon getDonutCoords(IFMEFeature feature) throws FMEException { IlvMapPolygon geom = null; IFMEFeatureVector featureVector = fmeSession.createFeatureVector(); feature.getDonutParts(featureVector); for (int j = 0; j < featureVector.entries(); j++) { IFMEFeature polygonFeature = featureVector.getAt(j); if (geom == null) { geom = new IlvMapPolygon(new IlvMapSegmentRing(getSimpleCoords(polygonFeature))); } else { geom.addInteriorRing(new IlvMapSegmentRing(getSimpleCoords(polygonFeature))); } polygonFeature.dispose(); polygonFeature = null; } featureVector.dispose(); featureVector = null; return geom; } private IlvMapGeometryCollection getAggregateCoords(IFMEFeature feature) throws FMEException { IlvMapGeometryCollection geom = new IlvMapGeometryCollection(); IFMEFeatureVector featureVector = fmeSession.createFeatureVector(); feature.splitAggregate(featureVector, false); for (int j = 0; j < featureVector.entries(); j++) { IFMEFeature featureElem = featureVector.getAt(j); geom.addGeometry(getFeatureCoords(featureElem)); featureElem.dispose(); featureElem = null; } featureVector.dispose(); featureVector = null; return geom; } static final private IlvWKTCoordinateSystemFactory wktf = new IlvWKTCoordinateSystemFactory(); /** * Reads the next JViews Feature and sets its geometry, attributes, and * possibly its coordinate system. * * @return The next JViews Maps feature in order. * @throws IOException */ public IlvMapFeature getNextFeature() throws IOException { IFMEFeature feature = fmeSession.createFeature(); IlvMapFeature ifeature = new IlvMapFeature(); try { String type = null; while (fmeReader.read(feature)) { type = feature.getFeatureType(); if (type != null && type.length() != 0) { break; } } if (type == null || type.length() == 0) { feature.dispose(); return null; } String coordsys = feature.getCoordSys(); if (coordsys != null && coordsys.length() != 0) { /* Perforce reproject */ String wkt = fmeSession.coordSysManager().getCoordSysAsOGCDef(coordsys); try { IlvCoordinateSystem cs = wktf.fromWKT(wkt); ifeature.setCoordinateSystem(cs); } catch (Exception e) { System.err.println("Cannot reproject feature " + e); //$NON-NLS-1$ // ignore } } IlvMapGeometry geom = getFeatureCoords(feature); ifeature.setGeometry(geom); IlvAttributeInfoProperty attrInfos = (IlvAttributeInfoProperty) fmeAttributeInfoProperties.get(type); if (attrInfos == null) { ArrayList<String> attributeNames = new ArrayList<String>(); feature.getAllAttributeNames(attributeNames); Iterator<?> iterator = attributeNames.iterator(); while (iterator.hasNext()) { String attributeName = (String) iterator.next(); if (attributeName.startsWith("*")) { //$NON-NLS-1$ iterator.remove(); } else if (attributeName.startsWith("fme_")) {//$NON-NLS-1$ iterator.remove(); } } attributeNames.add(IlvFMEReader.FME_FEATURE_TYPE); String names[] = (String[]) attributeNames.toArray(new String[0]); Class<?> classes[] = new Class[names.length]; boolean nullables[] = new boolean[names.length]; Arrays.fill(classes, IlvStringAttribute.class); Arrays.fill(nullables, true); attrInfos = new IlvAttributeInfoProperty(names, classes, nullables); fmeAttributeInfoProperties.put(type, attrInfos); } ifeature.setAttributeInfo(attrInfos); IlvFeatureAttribute values[] = new IlvFeatureAttribute[attrInfos.getAttributesCount()]; for (int i = 0; i < values.length; i++) { String attribute = attrInfos.getAttributeName(i); if (IlvFMEReader.FME_FEATURE_TYPE.equals(attribute)) { values[i] = new IlvStringAttribute(type); } else if (feature.attributeExists(attribute)) { values[i] = new IlvStringAttribute(feature.getStringAttribute(attribute)); } else { values[i] = null; } } ifeature.setAttributes(new IlvFeatureAttributeProperty(attrInfos, values)); } catch (FMEException e) { ifeature = null; throw new IOException(e.getMessage() + " " + e.getErrorNumber() + " " + e.getFMEStackTrace()); //$NON-NLS-1$//$NON-NLS-2$ } feature.dispose(); return ifeature; } }