arcgissamples\geodatabase\classextension\TimeStamper.java—ArcObjects 10.4 Help for Java | ArcGIS for Desktop
Time Stamper custom Java class extension
arcgissamples\geodatabase\classextension\TimeStamper.java
/* Copyright 2015 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 at <your ArcGIS install location>/DeveloperKit10.4/userestrictions.txt.
* 
*/
package arcgissamples.geodatabase.classextension;

import java.io.IOException;
import java.util.Date;

import com.esri.arcgis.geodatabase.*;
import com.esri.arcgis.interop.AutomationException;
import com.esri.arcgis.interop.extn.ArcGISCategories;
import com.esri.arcgis.interop.extn.ArcGISExtension;
import com.esri.arcgis.system.IPropertySet;
import com.esri.arcgis.system.PropertySet;

@ArcGISExtension(categories = { ArcGISCategories.GeoObjectClassExtensions })
public class TimeStamper implements IClassExtension, _IObjectClassEvents, IObjectClassExtension
{
    private static final long serialVersionUID = -4883301133761264384L;
    
    /**
     * The property set keys used to get and set the extension properties.
     */
    public final static String CREATED_FIELD_PROPERTY = "CREATION_FIELDNAME";
    public final static String MODIFIED_FIELD_PROPERTY = "MODIFICATION_FIELDNAME";
    public final static String USER_FIELD_PROPERTY = "USER_FIELDNAME";
    
    /**
     * The default field names to use as timestamp fields, if none are defined when the
     * class extension is applied.
     */
    private final static String DEFAULT_CREATED_FIELD = "CREATED";
    private final static String DEFAULT_MODIFIED_FIELD = "MODIFIED";
    private final static String DEFAULT_USER_FIELD = "USERNAME";
    
    /**
     * The indexes of the timestamp fields within the extension's class. A value of -1 indicates
     * that the field is not used, or could not be found during initialization.
     */
    private int createdFieldIndex = -1;
    private int modifiedFieldIndex = -1;
    private int userFieldIndex = -1;
    
    /**
     * The name that will be entered into the user field. On an ArcSDE geodatabase, this will be
     * the connected user, while on a local geodatabase this will be the user as specified by the
     * operating system. 
     */
    private String userName = "";
    
    /************************************************************************************************
     * com.esri.arcgis.geodatabase.IClassExtension 
     * This is the most crucial interface for Class Extensions. This is 
     * not optional and every class extension must implement this interface.  
     * If there is an error in your code here, none of your users will be able to access the data 
     * in the object class.
     ************************************************************************************************/
    /**
     * This method initializes the extension, passing in a reference to its class helper. This method is fired 
     * every time your object class is opened. If your object class is contained within a feature 
     * dataset, init() will fire as soon as any of the other feature classes are opened. 
     * Thus, within a feature dataset, if one feature class is opened, all the others are 
     * opened as well. This can cause your class extension's init() method to fire when 
     * you might not expect it. You will typically use init() to initialize objects you want to 
     * store at the class level. 
     */
    public void init(IClassHelper classHelper, IPropertySet extensionProperties) throws IOException, AutomationException
    {
        // Get a reference to the extension's object class.
        IClass baseClass = classHelper.esri_getClass();

        // Make sure a valid property set was provided.
        if (extensionProperties != null && extensionProperties.getCount() != 0)
        {
            // Get the field names from the property set.
            Object[] propertyKeysParam = new Object[1];
            Object[] propertyValuesParam = new Object[1];
            extensionProperties.getAllProperties(propertyKeysParam, propertyValuesParam);
            String[] propertyKeys = (String[])propertyKeysParam[0];
            Object[] propertyValues = (Object[])propertyValuesParam[0];
            
            // Iterate through the key/value pairs.
            for (int i = 0; i < propertyKeys.length; i++)
            {
                // Get the current key/value pair.
                String propertyKey = propertyKeys[i];
                String propertyValue = propertyValues[i].toString();
                
                if (propertyKey.equals(CREATED_FIELD_PROPERTY))
                {
                    createdFieldIndex = baseClass.findField(propertyValue);
                }
                
                if (propertyKey.equals(MODIFIED_FIELD_PROPERTY))
                {
                    modifiedFieldIndex = baseClass.findField(propertyValue);
                }
                
                if (propertyKey.equals(USER_FIELD_PROPERTY))
                {
                    userFieldIndex = baseClass.findField(propertyValue.toString());
                    userName = getUserName(baseClass);
                }
            }
        }
        else
        {
            // If the extension properties are null or empty, we can assume the class has
            // been created without extension properties. Apply the default property values.
            ISchemaLock schemaLock = null;
            try
            {
                // Attempt to acquire an exclusive schema lock. If this fails, an
                // AutomationException will be raised.
                schemaLock = new ISchemaLockProxy(classHelper.esri_getClass());
                schemaLock.changeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
                
                // Create a default set of extension properties.
                IPropertySet propertySet = new PropertySet();
                propertySet.setProperty(CREATED_FIELD_PROPERTY, DEFAULT_CREATED_FIELD);
                propertySet.setProperty(MODIFIED_FIELD_PROPERTY, DEFAULT_MODIFIED_FIELD);
                propertySet.setProperty(USER_FIELD_PROPERTY, DEFAULT_USER_FIELD);
                
                // Use the IClassSchemaEdit2 interface to persist a new set of
                // extension properties.
                IClassSchemaEdit2 classSchemaEdit2 = new IClassSchemaEdit2Proxy(classHelper.esri_getClass());
                classSchemaEdit2.alterClassExtensionProperties(propertySet);                
            }
            catch (AutomationException autoExc)
            {
                // An exclusive schema lock could not be acquired. Allow the extension to
                // finish initializing, but no custom behavior will occur.
            }
            finally
            {
                try
                {
                    // Ensure that the schema lock is shared.
                    if (schemaLock != null)
                        schemaLock.changeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
                }
                catch (Exception exc)
                {
                    // Ignore any errors at this point.
                }
            }
        }
    }    

    /**
     * Informs the extension that its class helper is going away.
     */
    public void shutdown() throws IOException, AutomationException
    {
        // Do nothing.
    }    

    /************************************************************************************************
     * com.esri.arcgis.geodatabase._IObjectClassEvents
     * This is a "fake" interface, in that it mimics the com.esri.arcgis.geodatabase.IObjectClassEvents. The events that IObjectClassEvents
     * is required to handle in Java have no COM counterparts, therefore a "fake" interface called _IObjectClassEvents was created that can
     * handle Java events derived from java.util.EventObject.
     ************************************************************************************************/
    /**
     * This event is fired when an object's attributes or geometry is updated.
     */
    public void onChange(IObject obj) throws IOException, AutomationException
    {
        // Make sure the modified field is defined.
        if (modifiedFieldIndex != -1)
        {
            obj.setValue(modifiedFieldIndex, new Date());
        }
        
        // If the user field is defined, set it as well.
        if (userFieldIndex != -1)
        {
            obj.setValue(userFieldIndex, userName);
        }
    }    

    /**
     * This event is fired when a new object is created in the object class.
     */
    public void onCreate(IObject obj) throws IOException, AutomationException
    {
        // Make sure the created field is defined.
        if (createdFieldIndex != -1)
        {
            obj.setValue(createdFieldIndex, new Date());
        }
        
        // If the user field is defined, set it as well.
        if (userFieldIndex != -1)
        {
            obj.setValue(userFieldIndex, userName);
        }
    }    

    /**
     * This event is fired when an object is deleted from the object class.
     */
    public void onDelete(IObject obj) throws IOException, AutomationException
    {
        // Do nothing.
    }    
    
    /********************************************************************************
     * Utils
     *********************************************************************************/
    /**
     * Returns the name of the user accessing the object class. If the class is in an ArcSDE
     * geodatabase, the connected user name will be returned, whereas if the class is in a
     * local geodatabase the OS user name will be used.
     */
    private String getUserName(IClass baseClass) throws IOException, AutomationException
    {
        String userName = null;
        
        // Check the class' workspace type.
        IDataset dataset = new IDatasetProxy(baseClass);
        Workspace workspace = new Workspace(dataset.getWorkspace());
        if (workspace.getType() == esriWorkspaceType.esriRemoteDatabaseWorkspace)
        {
            // The database is an ArcSDE database - get the connected user.
            userName = workspace.getConnectedUser();
        }
        else
        {
            // The database is local - get the system-defined user.
            userName = System.getProperty("user.name");
        }
        
        return userName;
    }  
}