arcgissamples\geodatabase\RelatedObjectsRunner.java
/* Copyright 2010 ESRI * * All rights reserved under the copyright laws of the United States * and applicable international laws, treaties, and conventions. * * You may freely redistribute and use this sample code, with or * without modification, provided you include the original copyright * notice and use restrictions. * * See the use restrictions. * */ package arcgissamples.geodatabase; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Enumeration; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory; import com.esri.arcgis.geodatabase.Feature; import com.esri.arcgis.geodatabase.FeatureClass; import com.esri.arcgis.geodatabase.FeatureCursor; import com.esri.arcgis.geodatabase.Field; import com.esri.arcgis.geodatabase.Fields; import com.esri.arcgis.geodatabase.GeometryDef; import com.esri.arcgis.geodatabase.Workspace; import com.esri.arcgis.geodatabase.esriFeatureType; import com.esri.arcgis.geodatabase.esriFieldType; import com.esri.arcgis.geodatabase.esriRelCardinality; import com.esri.arcgis.geodatabase.esriRelNotification; import com.esri.arcgis.geodatabase.esriSchemaLock; import com.esri.arcgis.geometry.GeographicCoordinateSystem; import com.esri.arcgis.geometry.ISpatialReference; import com.esri.arcgis.geometry.Line; import com.esri.arcgis.geometry.Point; import com.esri.arcgis.geometry.SpatialReferenceEnvironment; import com.esri.arcgis.geometry.esriGeometryType; import com.esri.arcgis.geometry.esriSRGeoCSType; import com.esri.arcgis.interop.extn.ArcGISExtension; import com.esri.arcgis.interop.extn.Bootstrapper; import com.esri.arcgis.system.AoInitialize; import com.esri.arcgis.system.EngineInitializer; import com.esri.arcgis.system.Set; import com.esri.arcgis.system.UID; import com.esri.arcgis.system.esriLicenseProductCode; import com.esri.arcgis.system.esriLicenseStatus; public class RelatedObjectsRunner { private static String outputPath = null; private Class ceClass = null; public static void main(String[] args) { try { //Get the ArcGIS Desktop runtime, if it is available String arcObjectsHome = System.getenv("AGSENGINEJAVA"); //If the ArcGIS Desktop runtime is not available, then report appropriate error to developer if(arcObjectsHome == null){ System.err.println("The RelatedObjectsRunner sample is designed to work with ArcGIS Engine installed."); System.err.println("You must install ArcGIS Engine and deploy the RelatedObjectsRunnerExt.jar as instructed " + "in this sample's ReadMe.htm file."); System.err.println("Exiting execution of this sample..."); System.exit(0); } String extensionJar = arcObjectsHome + "java" + File.separator + "lib" + File.separator + "ext" + File.separator + "RelatedObjectEventHandlerExt.jar"; RelatedObjectsRunner driver = new RelatedObjectsRunner(); //get output folder outputPath = getOutputDir(); if(driver.isJarFileValid(extensionJar)){ driver.ceClass = driver.getCEClass(extensionJar).get(0); } EngineInitializer.initializeEngine(); AoInitialize aoInit = new AoInitialize(); driver.initializeArcGISLicenses(aoInit); driver.driveExtension(); aoInit.shutdown(); } catch (Exception e){e.printStackTrace();} } /** * Convenience method to generate an output directory based on the operating * system that the sample is being executed on. * * @return A path to the new directory is return */ private static String getOutputDir() { String userDir; //Get the operating systems user profile or home location depending //on which operating system this sample is executed on. if(System.getProperty("os.name").toLowerCase().indexOf("win") > -1){ userDir = System.getenv("UserProfile"); }else{ userDir = System.getenv("HOME"); } String outputDir = userDir + File.separator + "arcgis_sample_output"; System.out.println("Creating output directory - " + outputDir); new File(outputDir).mkdir(); return outputDir; } void initializeArcGISLicenses(AoInitialize aoInit) { try { if (aoInit.isProductCodeAvailable(esriLicenseProductCode.esriLicenseProductCodeEngineGeoDB) == esriLicenseStatus.esriLicenseAvailable) aoInit.initialize(esriLicenseProductCode.esriLicenseProductCodeEngineGeoDB); } catch (Exception e) {e.printStackTrace();} } public void driveExtension() throws Exception { System.out.println("Starting RelatedObjectsRunner...\n"); System.out.print("Initializing data paths..."); String fgdbName = "relatedobjects.gdb"; System.out.println("Done."); System.out.print("Creating local File GDB..."); FileGDBWorkspaceFactory wsFactory = new FileGDBWorkspaceFactory(); wsFactory.create(outputPath, fgdbName, null, 0); System.out.println("Done."); System.out.println("Created a File GDB in the following location: " + outputPath + File.separator + fgdbName); //open the local workspace and create poles fc and transformer fc String polesFCName = "Pole"; String xformersFCName = "Transformer"; System.out.print("Creating " + polesFCName + " and " + xformersFCName + " feature classes in local File GDB..."); Workspace ws = (Workspace) wsFactory.openFromFile(outputPath + File.separator + fgdbName, 0); FeatureClass polesFC = createPolesFC(ws, polesFCName); FeatureClass xformerFC = createXFormerFC(ws, xformersFCName); System.out.println("Done."); System.out.print("Creating a composite Relationship Class between " + polesFCName + " and " + xformersFCName + " feature classes..."); /* * We are not using RelationshipClass.createRelationshipClass() method because we need to create a standalone relationship class. * IRelationshipClass.createRelationshipClass() is used when creating a relationship class inside a feature dataset. */ ws.createRelationshipClass("POLES_XFORMERS", polesFC, xformerFC, "Transformer", "Pole", esriRelCardinality.esriRelCardinalityOneToMany, esriRelNotification.esriRelNotificationForward, false, false, null, "OBJECTID", "", "poleid", ""); System.out.println("Done."); System.out.print("Adding extension to \"Transformer\"..."); /* * Use the RelatedObjectEventHandler CE as class extension to the xformer FC. * When a pole will be created the relatedObjectCreated() should be fired. */ if(xformerFC.getEXTCLSID() == null) { xformerFC.changeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock); //Create a new unique identifier object (UID) and assign the GUID to it. UID extUID = new UID(); extUID.setValue(ceClass); xformerFC.alterClassExtensionCLSID(extUID, null); xformerFC.changeSchemaLock(esriSchemaLock.esriSharedSchemaLock); } else { System.out.println("Cannot alter EXTCLSID for feature class. One already exists"); } System.out.println("Done."); try { ws.startEditing(false); ws.startEditOperation(); /* Rotate a feature in poles FC. When this feature is rotated, IRelatedObjectClassEvents.relatedObjectSetRotated() in the class * extension is fired and that gives you a chance to add custom logic to handle rotation. */ System.out.print("Rotating Pole features ..."); rotateFeatures(polesFC); System.out.println("Done."); /* * Move a pole feature. When this feature is moved, IRelatedObjectClassEvents.relatedObjectSetMoved() in the class * extension is fired and that gives you a chance to add custom logic to handle the move operation. */ System.out.print("Moving features ..."); moveFeatures(polesFC); System.out.println("Done."); ws.stopEditOperation(); ws.stopEditing(true); } catch(Exception e) { if(ws != null && ws.isBeingEdited()) { ws.stopEditing(false); } e.printStackTrace(); } System.out.println("\nRelated Objects Runner Done."); } /** * rotates certain features in specified feature class * @param featureClass * @throws Exception */ private void rotateFeatures(FeatureClass featureClass) throws Exception { //Create a set of features to rotate. int[] oidsToRotate = {1, 2}; Set featureSet = new Set(); for(int i = 0; i < oidsToRotate.length; i++) { Feature featureToRotate = (Feature) featureClass.getFeature(oidsToRotate[i]); featureSet.add(featureToRotate); } /* * Get a single feature and rotate it using rotationPoint and an angle */ //Create a rotation point. Point rotationPoint = new Point(); rotationPoint.setX(-117.4450); rotationPoint.setY(49.0166); //retrieve a feature Feature feature = (Feature) featureClass.getFeature(2); //rotate feature //no changes happen to feature. only features in feature set get rotated. feature.rotateSet(featureSet, rotationPoint, Math.PI); } /** * moves certain features in specified feature class * @param featureClass * @throws Exception */ private void moveFeatures(FeatureClass featureClass) throws Exception { //Create a set of features to move. int[] oidsToRotate = {1, 2, 3}; //4, 5, 6}; Set featureSet = new Set(); for(int i = 0; i < oidsToRotate.length; i++) { Feature featureToRotate = (Feature) featureClass.getFeature(oidsToRotate[i]); featureSet.add(featureToRotate); } /* * Create a move vector and move features along the vector */ //Create a move vector Point fromPoint = new Point(); fromPoint.setX(0); fromPoint.setY(0); Point toPoint = new Point(); toPoint.setX(0.1); toPoint.setY(0.1); Line moveVector = new Line(); moveVector.setFromPoint(fromPoint); moveVector.setToPoint(toPoint); // Get a single feature to access the IFeatureEdit interface. Feature feature = (Feature) featureClass.getFeature(2); feature.moveSet(featureSet, moveVector); } /** * Creates the XFormer FC * @param ws * @param polesFCName * @return * @throws Exception */ private FeatureClass createXFormerFC(Workspace ws, String xformerFCName) throws Exception { Fields fields = new Fields(); //OBJECTID field Field field = new Field(); field.setName("OBJECTID"); field.setType(esriFieldType.esriFieldTypeOID); fields.addField(field); field = null; //shape field field = new Field(); GeometryDef gdef = new GeometryDef(); gdef.setGeometryType(esriGeometryType.esriGeometryPoint); gdef.setHasM(false); gdef.setHasZ(false); SpatialReferenceEnvironment sre = new SpatialReferenceEnvironment(); GeographicCoordinateSystem gcs = (GeographicCoordinateSystem) sre.createGeographicCoordinateSystem(esriSRGeoCSType.esriSRGeoCS_NAD1983); gcs.setDomain(-400, 8099972.71208311, -400, 8099972.71208311); gdef.setSpatialReferenceByRef(gcs); field.setName("shape"); field.setType(esriFieldType.esriFieldTypeGeometry); field.setGeometryDefByRef(gdef); fields.addField(field); field = null; //pole id field field = new Field(); field.setName("poleid"); field.setType(esriFieldType.esriFieldTypeInteger); field.setEditable(true); fields.addField(field); field = null; //create and return feature class FeatureClass xformerFC = new FeatureClass(ws.createFeatureClass(xformerFCName, fields, null, null, esriFeatureType.esriFTSimple, "shape", "default")); System.out.println("Num features in polesFC before edit: " + xformerFC.featureCount(null)); ISpatialReference sr = xformerFC.getSpatialReference(); FeatureCursor featureCursor = new FeatureCursor(xformerFC.IFeatureClass_insert(true)); //add feature 1 Feature feature1 = (Feature) xformerFC.createFeature(); Point point1 = new Point(); point1.setX(-78.300683); point1.setY(34.099027); point1.setSpatialReferenceByRef(sr); feature1.setShapeByRef(point1); feature1.setValue(2, 1); feature1.store(); //add feature 2 Feature feature2 = (Feature) xformerFC.createFeature(); Point point2 = new Point(); point2.setX(-76.837546); point2.setY(29.709614); point2.setSpatialReferenceByRef(sr); feature2.setShapeByRef(point2); feature2.setValue(2, 1); feature2.store(); //add feature 3 Feature feature3 = (Feature) xformerFC.createFeature(); Point point3 = new Point(); point3.setX(-20.573254); point3.setY(75.465917); point3.setSpatialReferenceByRef(sr); feature3.setShapeByRef(point3); feature3.setValue(2, 2); feature3.store(); //add feature 4 Feature feature4 = (Feature) xformerFC.createFeature(); Point point4 = new Point(); point4.setX(4.965148); point4.setY(46.462838); point4.setSpatialReferenceByRef(sr); feature4.setShapeByRef(point4); feature4.setValue(2, 3); feature4.store(); //add feature 5 Feature feature5 = (Feature) xformerFC.createFeature(); Point point5 = new Point(); point5.setX(2.570923); point5.setY(28.778526); point5.setSpatialReferenceByRef(sr); feature5.setShapeByRef(point5); feature5.setValue(2, 3); feature5.store(); //add feature 6 Feature feature6 = (Feature) xformerFC.createFeature(); Point point6 = new Point(); point6.setX(9.354561); point6.setY(24.921164); point6.setSpatialReferenceByRef(sr); feature6.setShapeByRef(point6); feature6.setValue(2, 3); feature6.store(); featureCursor.flush(); featureCursor.release(); System.out.println("Num features in xformerFC after edit: " + xformerFC.featureCount(null)); return xformerFC; } /** * Creates the Pole FC * @param ws * @param polesFCName * @return * @throws Exception */ private FeatureClass createPolesFC(Workspace ws, String polesFCName) throws Exception { Fields fields = new Fields(); //OBJECTID field Field field = new Field(); field.setName("OBJECTID"); field.setType(esriFieldType.esriFieldTypeOID); fields.addField(field); field = null; //shape field field = new Field(); GeometryDef gdef = new GeometryDef(); gdef.setGeometryType(esriGeometryType.esriGeometryPoint); gdef.setHasM(false); gdef.setHasZ(false); SpatialReferenceEnvironment sre = new SpatialReferenceEnvironment(); GeographicCoordinateSystem gcs = (GeographicCoordinateSystem) sre.createGeographicCoordinateSystem(esriSRGeoCSType.esriSRGeoCS_NAD1983); gcs.setDomain(-400, 8099972.71208311, -400, 8099972.71208311); gdef.setSpatialReferenceByRef(gcs); field.setName("shape"); field.setType(esriFieldType.esriFieldTypeGeometry); field.setGeometryDefByRef(gdef); fields.addField(field); field = null; //create and return feature class FeatureClass polesFC = new FeatureClass(ws.createFeatureClass(polesFCName, fields, null, null, esriFeatureType.esriFTSimple, "shape", "default")); System.out.println("Num features in polesFC before edit: " + polesFC.featureCount(null)); ISpatialReference sr = polesFC.getSpatialReference(); FeatureCursor featureCursor = new FeatureCursor(polesFC.IFeatureClass_insert(true)); //add feature 1 Feature feature1 = (Feature) polesFC.createFeature(); Point point1 = new Point(); point1.setX(-77.236583); point1.setY(30.773714); point1.setSpatialReferenceByRef(sr); feature1.setShapeByRef(point1); feature1.store(); //add feature 2 Feature feature2 = (Feature) polesFC.createFeature(); Point point2 = new Point(); point2.setX(-18.711079); point2.setY(73.470370); point2.setSpatialReferenceByRef(sr); feature2.setShapeByRef(point2); feature2.store(); //add feature 3 Feature feature3 = (Feature) polesFC.createFeature(); Point point3 = new Point(); point3.setX(5.364185); point3.setY(24.123089); point3.setSpatialReferenceByRef(sr); feature3.setShapeByRef(point3); feature3.store(); //add feature 4 Feature feature4 = (Feature) polesFC.createFeature(); Point point4 = new Point(); point4.setX(-65.7057); point4.setY(68.0339); point4.setSpatialReferenceByRef(sr); feature4.setShapeByRef(point4); feature4.store(); featureCursor.flush(); featureCursor.release(); System.out.println("Num features in polesFC after edit: " + polesFC.featureCount(null)); return polesFC; } /* * Returns valid jar file path * @param jarFileName * @return */ private boolean isJarFileValid(String jarFilePath) throws FileNotFoundException { if(jarFilePath.length() == 0 || jarFilePath == null) { System.err.println("Error: Jar file path is empty, null or it contains invalid/unsupported characters."); System.exit(-1); } else { File jarFile = new File(jarFilePath); if(jarFile.exists()) { if(!jarFile.isFile() && !jarFilePath.endsWith(".jar")) { throw new FileNotFoundException("Jar file " + jarFile + " not found. Please verify if name of jar file containing Class Extension is correct."); } } } return true; } /* * Retrieve list of valid SOE classes in specified jar file */ private ArrayList<Class> getCEClass(String jarFilePath) { ArrayList<Class> ceClassList = new ArrayList<Class>(5); //validate input path if(System.getProperty("os.name").toLowerCase().startsWith("windows")) { if(jarFilePath.contains("Program Files")) { jarFilePath = jarFilePath.replace("Program Files", "Progra~1"); } else if(jarFilePath.contains("Program Files (x86)")) { jarFilePath = jarFilePath.replace("Program Files (x86)", "Progra~2"); } } //validate file indicated by jar file name. try { //load classes present inside jar file into memory Bootstrapper.loadExtensionJar(jarFilePath); //retrieve individual contents of jar file JarFile jarFile = new JarFile(jarFilePath); Enumeration<JarEntry> jarContents = jarFile.entries(); while (jarContents.hasMoreElements()) { ZipEntry zipEntry = (ZipEntry) jarContents.nextElement(); if(!zipEntry.isDirectory()) { //ignore current file if it does not end with .class String fileName = zipEntry.getName(); if(fileName.endsWith(".class")) { //retrieve the Class object for current class file String ceFullyQualifiedName = fileName.replace('/', '.').substring(0, fileName.length() - ".class".length()); Class classDef = Class.forName(ceFullyQualifiedName); //consider class only if its not an interface and its annotated with ArcGISExtension if(!classDef.isInterface() && classDef.isAnnotationPresent(ArcGISExtension.class)) { //add the class to a list ceClassList.add(classDef); } } } } //trim the list ceClassList.trimToSize(); //if list is of size 0 if(ceClassList.size() <= 0) { System.err.println("\nError: No .class files or .class files containing Class Extension found in " + jarFilePath); } //return it return ceClassList; } catch (IOException e) { e.printStackTrace(); } catch(ClassNotFoundException ce) { ce.printStackTrace(); } return null; } /** * Creates a new directory * @param pathName String */ public void createFolder(String pathName) { File f = new File(pathName); if (!f.exists()) { f.mkdir(); } } /** * Empties specified directory of all files * @param dirName String */ public void emptyFolder(String dirName, boolean includeSubFolder) throws Exception { File src = new File(dirName); if (src.isDirectory() && src.exists()) { File list[] = src.listFiles(); for (int i = 0; i < list.length; i++) { if (includeSubFolder && list[i].isDirectory()) { emptyFolder(list[i].getPath(), includeSubFolder); list[i].delete(); } else { list[i].delete(); } } } else { throw new Exception("MatrixUtil.emptyFolder() - " + dirName + " is not a directory or does not exist."); } } /** * Empties specified directory of all files * @param dirName String */ public void deleteFolder(String dirName) throws Exception { File src = new File(dirName); if (src.isDirectory() && src.exists()) { File list[] = src.listFiles(); for (int i = 0; i < list.length; i++) { if (list[i].isDirectory()) { emptyFolder(list[i].getPath(), true); list[i].delete(); } else { list[i].delete(); } } src.delete(); } else { src.delete(); } } /** * Empties specified directory of all files * @param dirName String */ public void deleteFile(String fullyQualifiedFileName) throws Exception { File file = new File(fullyQualifiedFileName); if(!file.isDirectory() && file.exists()) { file.delete(); } else { throw new Exception("MatrixUtil.deleteFile() - File " + fullyQualifiedFileName + " does not exist or is a directory."); } } }