How to get domain values from sub type?

1889
5
Jump to solution
04-05-2018 07:57 PM
BatbayarBazarragchaa
New Contributor III

I've defined sub types for my feature class and some fields have different domain values for each sub type.

And I've exposed it as a feature service and trying to get domain and its values for each different sub type.

But when I get domain (AGSCodedValueDomain) from field (AGSField) it returns same domain for each sub type.

So I've tried to get domain from sub type (AGSFeatureType) but it returns AGSInheritedDomain, which I couldn't figure out how to get coded values.

Arcgis feature service version: 10.4.1

SDK version 100.2.1

Language: Swift

0 Kudos
1 Solution

Accepted Solutions
Nicholas-Furness
Esri Regular Contributor

Hi,

Update 3 of the runtime (due in the June timeframe) will expose Subtypes through the API.

I'm afraid that in the meantime you'll have to get the metadata from the REST endpoint and parse out the information yourself (as you mention, you'll need to upgrade your server). This code might help point you in the right direction:

func parseSubtypeInfo(forServiceFeatureTable featureTable:AGSServiceFeatureTable) {
    guard let url = featureTable.url else {
        return
    }

    let operation = AGSJSONRequestOperation(remoteResource: featureTable,
                                            url: url,
                                            queryParameters: nil)
    operation.registerListener(AGSOperationQueue.shared()) { (jsonResult, error) in
        guard error == nil else {
            print("Error loading resources: \(error!.localizedDescription)")
            return
        }

        guard let jsonDict = jsonResult as? [String:Any] else {
            print("JSON not a dictionary!")
            return
        }

        guard let subtypeField = jsonDict["subtypeField"] as? String,
            let defaultSubtypeCode = jsonDict["defaultSubtypeCode"] as? Int,
            let subtypes = jsonDict["subtypes"] as? [[String:Any]] else {
                print("Couldn't find Subtype info")
                return
        }

        print("Subtype Field: \(subtypeField)")
        // subtypes is now an Array of subtype definition Dictionaries.
    }

    AGSOperationQueue.shared().addOperation(operation)
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope this helps,

Nick.

View solution in original post

5 Replies
RobertBorchert
Frequent Contributor III

From ArcCatalog export the database as an XML Workspace Document.  Just do schema only.

then open the XML in MS Excel.  While the result will not be pretty.  You can do some simple Analysis and you will be able to find all your Subtypes, each attribute in the subtype, each domain attached to that attribute and each value of the domain.

0 Kudos
BatbayarBazarragchaa
New Contributor III

So with this solution I have to locally store the domain information on the mobile device and have to release an update when the domain values are updated. So its not a good solution.

It seems like there's another way to get domains from REST service, but its available from Arcgis 10.5, so I have to update my feature service. Its the query domains service but I haven't tried yet:

Query Domains (Feature Service)—ArcGIS REST API: Services Directory | ArcGIS for Developers 

0 Kudos
Nicholas-Furness
Esri Regular Contributor

Hi,

Update 3 of the runtime (due in the June timeframe) will expose Subtypes through the API.

I'm afraid that in the meantime you'll have to get the metadata from the REST endpoint and parse out the information yourself (as you mention, you'll need to upgrade your server). This code might help point you in the right direction:

func parseSubtypeInfo(forServiceFeatureTable featureTable:AGSServiceFeatureTable) {
    guard let url = featureTable.url else {
        return
    }

    let operation = AGSJSONRequestOperation(remoteResource: featureTable,
                                            url: url,
                                            queryParameters: nil)
    operation.registerListener(AGSOperationQueue.shared()) { (jsonResult, error) in
        guard error == nil else {
            print("Error loading resources: \(error!.localizedDescription)")
            return
        }

        guard let jsonDict = jsonResult as? [String:Any] else {
            print("JSON not a dictionary!")
            return
        }

        guard let subtypeField = jsonDict["subtypeField"] as? String,
            let defaultSubtypeCode = jsonDict["defaultSubtypeCode"] as? Int,
            let subtypes = jsonDict["subtypes"] as? [[String:Any]] else {
                print("Couldn't find Subtype info")
                return
        }

        print("Subtype Field: \(subtypeField)")
        // subtypes is now an Array of subtype definition Dictionaries.
    }

    AGSOperationQueue.shared().addOperation(operation)
}
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Hope this helps,

Nick.

Nicholas-Furness
Esri Regular Contributor

You might also find this answer useful determining the actual domain that's being inherited in a subtype

0 Kudos
ShiminCai
Occasional Contributor III

Hi,

I'm still on SDK 10.2.5. I use the below funcs to get subtype description domain:

func getSubtypeDescriptionDomain(_ subtypeCode: Int, forDescriptionField subtypeDescriptionField: String, forGDBFeatureSourceInfo gdbFeatureSourceInfo: AGSGDBFeatureSourceInfo) -> AGSDomain

    {

        var domain: AGSDomain!

    

        for type in gdbFeatureSourceInfo.types

        {

            if((type as AnyObject).typeId as! Int == subtypeCode)

            {

                for (key, value) in (type as AnyObject).domains!

                {

                    if(subtypeDescriptionField == key as! String)

                    {

                        domain = value as! AGSDomain

                        return domain

                    }

                }

            }

        }

        return domain

    }

The subtypeCode is from the subtype field of a feature class that has subtype defined. The subtypeDescriptionField is the string field name to get domain from for the subtypeCode. The gdbFeatureSourceInfo is an instance of AGSFeatureLayer from a feature service or AGSGDBFeatureTable from a geodatabase downloaded in code from the feature service.

This is to determine if a field is a subtype description field:

func isSubtypeDescriptionField(_ subtypeCode: Int, forFieldName fieldName: String, forGDBFeatureSourceInfo gdbFeatureSourceInfo: AGSGDBFeatureSourceInfo) -> Bool

    {

        var subtypeDescriptionField = false

    

        for type in gdbFeatureSourceInfo.types

        {

            if((type as AnyObject).typeId as! Int == subtypeCode)

            {

                for (key, _) in (type as AnyObject).domains!

                {

                    if(fieldName == key as! String)

                    {

                        subtypeDescriptionField = true

                        return subtypeDescriptionField

                    }

                }

            }

        }

    

        return subtypeDescriptionField

    }

Hope it helps.

Shimin