Select to view content in your preferred language

Get GroupLayer Name

3691
20
07-29-2013 10:00 AM
LeoDonahue
Deactivated User
ArcObjects Java 10.0 sp5

If an IGroupLayer is composed of IFeatureLayers, the following code will print the IGroupLayer name.

If I pass a name that I *think* is an IGroupLayer, my method crashes with null pointer.  So, if you have a map document with a mosaic with sub layers: Boundary, Footprint and Image, is that not an IGroupLayer?  I've also tried ICompositeLayer also, with the same null pointer result.

If I pass the name of my mosaic layer to the following method, I get a null pointer.
If pass the name of any other group layer, it will print the parent group name, in this example "Transportation".

    public IGroupLayer getGroupLayerName(com.esri.arcgis.carto.Map map, AGSConnection agsconn){
        ILayer layer = null;
        
        try {
            
            UID id = (UID) agsconn.getContext().createObject(UID.getClsid());
            id.setValue(com.esri.arcgis.carto.IGroupLayer.class);
            
            // getLayers(UID, true) uses recursion to the get the layer name in a GroupLayer
            IEnumLayer enumLayer = map.getLayers(id, true);
            enumLayer.reset();
            layer = enumLayer.next();
            
            while(!(layer == null)){
                if(layer.getName().equalsIgnoreCase("Transportation")){
                    break;
                } else {
                    layer = enumLayer.next();
                }
            }
        } catch (AutomationException ae) {
            ae.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            System.out.println(layer.getName());
        } catch (AutomationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return (IGroupLayer) layer;
    }


This method can find the layer named "Image" located within the Mosaic layer, but I really wanted the name of the mosaic group layer.

    public IRasterLayer getRasterLayerName(com.esri.arcgis.carto.Map map, AGSConnection agsconn){
        ILayer layer = null;
        
        try {
            
            UID id = (UID) agsconn.getContext().createObject(UID.getClsid());
            id.setValue(com.esri.arcgis.carto.IRasterLayer.class);
            
            // getLayers(UID, true) uses recursion to the get the layer name in a GroupLayer
            IEnumLayer enumLayer = map.getLayers(id, true);
            enumLayer.reset();
            layer = enumLayer.next();
            
            while(!(layer == null)){
                if(layer.getName().equalsIgnoreCase("Image")){
                    break;
                } else {
                    layer = enumLayer.next();
                }
            }
        } catch (AutomationException ae) {
            ae.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return (IRasterLayer) layer;
    }
0 Kudos
20 Replies
T__WayneWhitley
Honored Contributor
I don't know if you found your answer, but can't you get this through IMosaicLayer interface?--
http://help.arcgis.com/en/sdk/10.0/java_ao_adf/api/arcobjects/com/esri/arcgis/carto/IMosaicLayer.htm...
0 Kudos
LeoDonahue
Deactivated User
Wayne,

Maybe? 

I think my problem is that I have two  group layers in my map document.  One is a transportation group layer,  based on feature layers and the other is a mosaic layer, and I"m using:

IEnumLayer enumLayer = map.getLayers(id, true);

Apparently this does not work for GroupLayers that are MosaicLayers.

When I run the following code, the while loop prints: "Transporation is not an instance of MosaicLayer", but then the while loop terminates after that because layer is now null.  It's not picking up the MosaicLayer at all.

All I want is to get the Mosaic layer and set its visibility to false.  I can't even get the name of the Mosaic Layer without either null pointers or messages indicating that GroupLayer.getName() is unknown.

    public ILayer getGroupLayerName(com.esri.arcgis.carto.Map map, AGSConnection agsconn){
        ILayer layer = null;
        
        try {
            
            UID id = (UID) agsconn.getContext().createObject(UID.getClsid());
            id.setValue(com.esri.arcgis.carto.IGroupLayer.class);
            
            // getLayers(UID, true) uses recursion to the get the layer name in a GroupLayer
            IEnumLayer enumLayer = map.getLayers(id, true);
            enumLayer.reset();
            layer = enumLayer.next();
            
            while(!(layer == null)){
                if(layer instanceof MosaicLayer){
                    if(layer.getName().equalsIgnoreCase("Aerial2011Sep_2011Oct_Ortho")){
                        System.out.println(((MosaicLayer) layer).getName());
                        break;
                    } else {
                        layer = enumLayer.next();
                    }
                } else {
                    System.out.println(layer.getName() + " is not an instance of MosaicLayer");
                    layer = enumLayer.next();
                }
            }
        } catch (AutomationException ae) {
            ae.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return (ILayer) layer;
    }
0 Kudos
LeoDonahue
Deactivated User
I think this is impossible in Java.

If I don't append the getName method call, this code will print "com.esri.arcgis.carto.GroupLayer" twice. 

So I guess, a mosaic dataset added from a FGDB is a GroupLayer?  I don't see that connection in the API. 
IGroupLayer has no base class for mosaics. 
ICompositeLayer does though.

Once I append the getName method call, this code will print:

INFO: Server startup in 23074 ms
com.esri.arcgis.carto.GroupLayer Transportation  // yes!  this is one of the group layers
Jul 29, 2013 3:46:51 PM com.sun.faces.application.ActionListenerImpl processAction
SEVERE: java.lang.ClassCastException: A COM object reference via iid 34c20002-4d3c-11d0-92d8-00805f7c28b0 does not support COM interface edad6644-1810-11d1-86ae-0000f8751720
javax.faces.el.EvaluationException: java.lang.ClassCastException: A COM object reference via iid 34c20002-4d3c-11d0-92d8-00805f7c28b0 does not support COM interface edad6644-1810-11d1-86ae-0000f8751720
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:98)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:98)
    at javax.faces.component.UICommand.broadcast(UICommand.java:311)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:781)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1246)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:77)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassCastException: A COM object reference via iid 34c20002-4d3c-11d0-92d8-00805f7c28b0 does not support COM interface edad6644-1810-11d1-86ae-0000f8751720
    at com.esri.arcgis.interop.Dispatch.c(Unknown Source)
    at com.esri.arcgis.interop.Dispatch.vtblInvoke(Unknown Source)
    at com.esri.arcgis.carto.ILayerProxy.getName(Unknown Source)
    at com.esri.arcgis.carto.GroupLayer.getName(Unknown Source)
    at blah.blah.blah.printMosaicLayerName(MyClassName.java:92)


Line 92 is highlighted below in red.

    public void printMosaicLayerName(com.esri.arcgis.carto.Map map, AGSConnection agsconn){
        ILayer layer = null;
        
        try {
            
            UID id = (UID) agsconn.getContext().createObject(UID.getClsid());
            id.setValue(com.esri.arcgis.carto.ICompositeLayer.class);
            
            // getLayers(UID, true) uses recursion to the get the layer name in a GroupLayer
            IEnumLayer enumLayer = map.getLayers(id, true);
            enumLayer.reset();
            layer = (ILayer) enumLayer.next();
            
            while(!(layer == null)){
                System.out.println(layer.getClass().getName() + " " + layer.getName());
                layer = (ILayer) enumLayer.next();
            }
        } catch (AutomationException ae) {
            ae.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
0 Kudos
T__WayneWhitley
Honored Contributor
I may be oversimplifying but I thought the mosaic layer was considered a 'special layer', not a run-of-the-mill composite layer.  And as such, special access has been provided?

Not that I know this is a good suggestion (or for that matter am I qualified enough to write the code), but ILayer2 is documented in the 'All Known Implementing Classes' to include the MosaicLayer class.

http://help.arcgis.com/en/sdk/10.0/java_ao_adf/api/arcobjects/com/esri/arcgis/carto/ILayer2.html

Theoretically, via the MosaicLayer class, you will have the proper access to the setVisible method (and getName() too).


I may be all wrong about this, but was interested in case you're out of ideas...

-Wayne
0 Kudos
LeoDonahue
Deactivated User
I am officially out of ideas.

I changed interfaces to ILayer2.  Doing so will now print every layer recursively (including the GroupLayer name), except the mosaic layer.

The error is on the same line as before, where it seems as though a mosaic is considered a "GroupLayer", but why I can't get the name of it I have no clue.


The code:
    public void printMosaicLayerName(com.esri.arcgis.carto.Map map, AGSConnection agsconn){
        ILayer2 layer = null;
        
        try {
            
            UID id = (UID) agsconn.getContext().createObject(UID.getClsid());
            id.setValue(com.esri.arcgis.carto.ILayer2.class);
            
            // getLayers(UID, true) uses recursion to the get the layer name in a GroupLayer
            IEnumLayer enumLayer = map.getLayers(id, true);
            enumLayer.reset();
            layer = (ILayer2) enumLayer.next();
            
            while(!(layer == null)){
                System.out.println(layer.getClass().getName() + " " + layer.getName());  // this is line #93
                if(layer instanceof IMosaicDataset){
                    MosaicDataset md = (MosaicDataset)layer;
                    System.out.println(md.getRelativePath().toString());
                } 
                layer = (ILayer2) enumLayer.next();
            }
        } catch (AutomationException ae) {
            ae.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


The output:

*Note:  all the lines prior to the "Caused by:" are related to the UI not loading becuase of this ClassCastException. I expected to see this in the log.

Jul 31, 2013 7:37:43 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 23085 ms
com.esri.arcgis.carto.FeatureLayer Zoning Case
com.esri.arcgis.carto.GroupLayer Transportation          // The next 5 layers are part of the Transporation GroupLayer
com.esri.arcgis.carto.FeatureLayer Residential Streets
com.esri.arcgis.carto.FeatureLayer Major Roads
com.esri.arcgis.carto.FeatureLayer State Highway
com.esri.arcgis.carto.FeatureLayer US Highway
com.esri.arcgis.carto.FeatureLayer Interstates
com.esri.arcgis.carto.FeatureLayer County Boundary
com.esri.arcgis.carto.FeatureLayer Parcels               //  Right after this layer is the mosaic
Jul 31, 2013 7:38:16 AM com.sun.faces.application.ActionListenerImpl processAction
SEVERE: java.lang.ClassCastException: A COM object reference via iid 34c20002-4d3c-11d0-92d8-00805f7c28b0 does not support COM interface edad6644-1810-11d1-86ae-0000f8751720
javax.faces.el.EvaluationException: java.lang.ClassCastException: A COM object reference via iid 34c20002-4d3c-11d0-92d8-00805f7c28b0 does not support COM interface edad6644-1810-11d1-86ae-0000f8751720
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:98)
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:98)
    at javax.faces.component.UICommand.broadcast(UICommand.java:311)
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:781)
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1246)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:77)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
    at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.ClassCastException: A COM object reference via iid 34c20002-4d3c-11d0-92d8-00805f7c28b0 does not support COM interface edad6644-1810-11d1-86ae-0000f8751720
    at com.esri.arcgis.interop.Dispatch.c(Unknown Source)
    at com.esri.arcgis.interop.Dispatch.vtblInvoke(Unknown Source)
    at com.esri.arcgis.carto.ILayerProxy.getName(Unknown Source)
    at com.esri.arcgis.carto.GroupLayer.getName(Unknown Source)
    at blah.blah.blah.printMosaicLayerName(MyClassName.java:93)
0 Kudos
LeoDonahue
Deactivated User
If I remove the call to getName from line 93, it will print the following:

System.out.println(layer.getClass().getName() );

com.esri.arcgis.carto.FeatureLayer
com.esri.arcgis.carto.GroupLayer
com.esri.arcgis.carto.FeatureLayer
com.esri.arcgis.carto.FeatureLayer
com.esri.arcgis.carto.FeatureLayer
com.esri.arcgis.carto.FeatureLayer
com.esri.arcgis.carto.FeatureLayer
com.esri.arcgis.carto.FeatureLayer
com.esri.arcgis.carto.FeatureLayer
com.esri.arcgis.carto.GroupLayer
com.esri.arcgis.carto.FeatureLayer
com.esri.arcgis.carto.FeatureLayer


This tells me I have a "GroupLayer" class.  Now why can't I get the name of it?

[ATTACH=CONFIG]26345[/ATTACH]
0 Kudos
T__WayneWhitley
Honored Contributor
That's interesting --- I haven't experimented with this yet and frankly I haven't fiddled with ArcObjects in awhile, but according to the arcobjects (and arcgis desktop) documentation, a mosaic layer is a 'special entity'.  Conceptually, I'm still trying to wrap my head around this but I think the same group or composite layer methods do not apply to this type of layer, the mosaic layer....why I think the mosaiclayer co-class was made; however, how do you use those methods?  I'll try to find some examples, I think even some VB.net examples may help you since good Java examples seem to be lacking.

Very interesting problem, I have to say.  Please post the answer if you find it.

-Wayne
0 Kudos
LeoDonahue
Deactivated User
....however, how do you use those methods?


For IGroupLayer or IFeatureLayer or IRasterLayer, I can get the name.  It seems as though if the group layer is a mosaic group layer, I can't get the name.  These layers are in a published map in ArcGIS Server.

Originally, I just wanted to find the layer in the TOC by name, and toggle the visibility.  My original post shows how I'm going around this by getting the feature layer named "Image" (which is part of the mosaic group layer) using this method: 

public IRasterLayer getRasterLayerName(com.esri.arcgis.carto.Map map, AGSConnection agsconn)


But no, I'm stubborn, I have to waste time figuring out why I can't do something easy - because it's bugging me.

I suppose I can rename the "Image" part of the mosaic layer to the mosaic layer group name, in case I add additional mosaics to this project in the future.

This really started out as a simple project, a web app to generate zoning case maps dynamically using iText and extracting the feature attributes from a separate enterprise database into the pdf.  It's been working fine for weeks.

Then came the final "last minute" requirement:  "Can we let the user toggle the aerial photos on/off ?"  Sounds easy... hahaha..

The UI:
[ATTACH=CONFIG]26350[/ATTACH]
0 Kudos
T__WayneWhitley
Honored Contributor
I'm not at all familiar with Java, but if you'll forgive me 'dumbing' this down for a moment, I'm interested in this mosaic layer 'thing'.
This may not be implemented in Java the same way, but I did some rudimentary 'quick' testing in VBA and it seems if looping through the layers in the TOC to get the layer name, let's say, then you can test if a composite layer AND mosaic layer...and via ILayer (or ILayer2) toggle visibility off (or query the layer name, etc., if need be beforehand).

And if you 'cast' (if I'm using the term correctly) the ILayer object as an IMosaicLayer object, then there's access to the Boundary, Footprint, Raster Dataset Mosaic 'sublayers' -- probably this VB below is easy for you to follow (again, no idea how this is implemented in Java).  What I did (without bothering to auto-refresh the view/TOC in ArcMap) is in successive runs, prove that the ILayer 'handle' works to turn on/off the Mosaic layer and IMosaicLayer 'handle' works to turn on/off the sub layers associated with the Mosaic layer.

I apologize for my clumsy explanation, but maybe this will help and I'd be interested to know if this 'translates' or is applicable to what you're doing in Java (code window below).

Please post if you have anything different - I'd like to see the Java code solution.

Enjoy,
Wayne

Public Sub ToggleMosaicLayerVis()
    Dim pMxDoc As IMxDocument
    Set pMxDoc = ThisDocument

    Dim pCpsLyr As ILayer2  'ILayer works too
    
    'accessing 1st layer in TOC; incidentally a mosaic layer
    Set pCpsLyr = pMxDoc.FocusMap.Layer(0)

    'this works, but obviously did not apply any layer prop testing
    If pCpsLyr.Visible = True Then
        pCpsLyr.Visible = False
    Else
        pCpsLyr.Visible = True
    End If
    
    Debug.Print "Your 'composite mosaic' layer name = " & pCpsLyr.Name
    Debug.Print "...and the layer visibility is set " & pCpsLyr.Visible
    
    ' some interesting lyr testing; both composite and mosaic tested true
    If TypeOf pCpsLyr Is IMosaicLayer Then
        Debug.Print "True mosaic"
    End If
    If TypeOf pCpsLyr Is ICompositeLayer Then
        Debug.Print "True composite"
    End If
    If TypeOf pCpsLyr Is IFeatureLayer Then
        Debug.Print "True feature"
    End If
    
    ' stupid pet trick to see how ILayer2 obj is extended as IMosaicLayer obj
    ' now access is extended to set visibility on sublayers associated with mosaic lyr
    Dim pMscLyr As IMosaicLayer
    Set pMscLyr = pCpsLyr
    If pCpsLyr.Visible = True Then
        If pMscLyr.BoundaryLayer.Visible = True Then
            pMscLyr.BoundaryLayer.Visible = False
        Else: pMscLyr.BoundaryLayer.Visible = True
        End If
    End If

    'Debug.Print pMscLyr.MosaicDataset.VisibleFields
    'Debug.Print pMscLyr.PreviewLayer.Name
    
End Sub



This concludes this oversimplification, for what it's worth.... and by the way, these are the debug print statements (run twice of course):

Your 'composite mosaic' layer name = testMosaicDS_MosaicLayer
...and the layer visibility is set True
True mosaic
True composite
Your 'composite mosaic' layer name = testMosaicDS_MosaicLayer
...and the layer visibility is set False
True mosaic
True composite
0 Kudos