private <N> void addMetricAndAvailInstances(
      ID resourceId,
      ResourceType<L> type,
      L parentLocation,
      N baseNode,
      Resource.Builder<L> builder,
      Session<L> session) {

    for (MetricType<L> metricType : type.getMetricTypes()) {
      AttributeLocation<L> location = metricType.getAttributeLocation();
      try {
        final AttributeLocation<L> instanceLocation =
            session.getLocationResolver().absolutize(parentLocation, location);
        if (session.getDriver().attributeExists(instanceLocation)) {
          ID id =
              InventoryIdUtil.generateMetricInstanceId(session.getFeedId(), resourceId, metricType);
          Name name = metricType.getName();

          MeasurementInstance<L, MetricType<L>> metricInstance =
              new MeasurementInstance<>(id, name, instanceLocation, metricType);
          builder.metric(metricInstance);
        }
      } catch (ProtocolException e) {
        log.warnFailedToLocate(
            e,
            metricType.getClass().getName(),
            String.valueOf(location),
            String.valueOf(parentLocation));
      }
    }

    for (AvailType<L> availType : type.getAvailTypes()) {
      AttributeLocation<L> location = availType.getAttributeLocation();
      try {
        final AttributeLocation<L> instanceLocation =
            session.getLocationResolver().absolutize(parentLocation, location);
        if (session.getDriver().attributeExists(instanceLocation)) {
          ID id =
              InventoryIdUtil.generateAvailInstanceId(session.getFeedId(), resourceId, availType);
          Name name = availType.getName();

          MeasurementInstance<L, AvailType<L>> availInstance =
              new MeasurementInstance<>(id, name, instanceLocation, availType);
          builder.avail(availInstance);
        }
      } catch (ProtocolException e) {
        log.warnFailedToLocate(
            e,
            availType.getClass().getName(),
            String.valueOf(location),
            String.valueOf(parentLocation));
      }
    }
  }
  private <N> void discoverResourceConfiguration(
      ID resourceId,
      ResourceType<L> type,
      L parentAddress,
      N baseNode,
      Resource.Builder<L> builder,
      Session<L> session) {

    Collection<ResourceConfigurationPropertyType<L>> confPropTypes =
        type.getResourceConfigurationPropertyTypes();
    for (ResourceConfigurationPropertyType<L> confPropType : confPropTypes) {
      try {
        final AttributeLocation<L> location = confPropType.getAttributeLocation();
        final LocationResolver<L> locationResolver = session.getLocationResolver();
        final AttributeLocation<L> instanceLocation =
            locationResolver.absolutize(parentAddress, location);
        final Driver<L> driver = session.getDriver();

        String resConfPropValue;

        if (!locationResolver.isMultiTarget(instanceLocation.getLocation())) {
          Object o = driver.fetchAttribute(instanceLocation);
          resConfPropValue = ((o == null) ? null : o.toString());
        } else {
          // This resource config is a conglomeration of attrib values across multiple locations. We
          // need to
          // aggregate them all into a map and store the map as the resource configuration property
          // value.
          Map<L, Object> attribMap = driver.fetchAttributeAsMap(instanceLocation);
          if (attribMap == null || attribMap.isEmpty()) {
            resConfPropValue = null;
          } else {
            Map<String, String> resConfigPropMap = new HashMap<>(attribMap.size());
            L multiTargetLocation = instanceLocation.getLocation();
            for (Map.Entry<L, Object> entry : attribMap.entrySet()) {
              L singleLocation = entry.getKey();
              String attribValue = String.valueOf(entry.getValue());
              String attribKey =
                  locationResolver.findWildcardMatch(multiTargetLocation, singleLocation);
              resConfigPropMap.put(attribKey, attribValue);
            }
            resConfPropValue = Util.toJson(resConfigPropMap);
          }
        }

        ResourceConfigurationPropertyInstance<L> cpi =
            new ResourceConfigurationPropertyInstance<>(
                ID.NULL_ID,
                confPropType.getName(),
                instanceLocation,
                confPropType,
                resConfPropValue);

        builder.resourceConfigurationProperty(cpi);
      } catch (Exception e) {
        log.warnf(
            e, "Failed to discover config [%s] for resource [%s]", confPropType, parentAddress);
      }
    }
  }