private static <T> T decodePropertyValue(
     String fullPropertyName,
     @Nullable String propertyValue,
     Class<T> type,
     PropertyMetadata<?> metadata) {
   if (metadata.getJavaType() != type) {
     throw new PrestoException(
         INVALID_SESSION_PROPERTY,
         format(
             "Property %s is type %s, but requested type was %s",
             fullPropertyName, metadata.getJavaType().getName(), type.getName()));
   }
   if (propertyValue == null) {
     return type.cast(metadata.getDefaultValue());
   }
   Object objectValue = deserializeSessionProperty(metadata.getSqlType(), propertyValue);
   try {
     return type.cast(metadata.decode(objectValue));
   } catch (PrestoException e) {
     throw e;
   } catch (Exception e) {
     // the system property decoder can throw any exception
     throw new PrestoException(
         INVALID_SESSION_PROPERTY,
         format("%s is invalid: %s", fullPropertyName, propertyValue),
         e);
   }
 }
  public <T> T decodeProperty(String name, @Nullable String value, Class<T> type) {
    requireNonNull(name, "name is null");
    requireNonNull(type, "type is null");

    SessionProperty<?> sessionProperty = allSessionProperties.get(name);
    if (sessionProperty == null) {
      throw new PrestoException(INVALID_SESSION_PROPERTY, "Unknown session property " + name);
    }
    PropertyMetadata<?> metadata = sessionProperty.getMetadata();
    if (metadata.getJavaType() != type) {
      throw new PrestoException(
          INVALID_SESSION_PROPERTY,
          format(
              "Property %s is type %s, but requested type was %s",
              name, metadata.getJavaType().getName(), type.getName()));
    }
    if (value == null) {
      return type.cast(metadata.getDefaultValue());
    }
    Object objectValue = deserializeSessionProperty(metadata.getSqlType(), value);
    try {
      return type.cast(metadata.decode(objectValue));
    } catch (PrestoException e) {
      throw e;
    } catch (Exception e) {
      // the system property decoder can throw any exception
      throw new PrestoException(
          INVALID_SESSION_PROPERTY, format("%s is invalid: %s", name, value), e);
    }
  }
  public List<SessionPropertyValue> getAllSessionProperties(
      Session session, Map<String, ConnectorId> catalogs) {
    requireNonNull(session, "session is null");

    ImmutableList.Builder<SessionPropertyValue> sessionPropertyValues = ImmutableList.builder();
    Map<String, String> systemProperties = session.getSystemProperties();
    for (PropertyMetadata<?> property : systemSessionProperties.values()) {
      String defaultValue = firstNonNull(property.getDefaultValue(), "").toString();
      String value = systemProperties.getOrDefault(property.getName(), defaultValue);
      sessionPropertyValues.add(
          new SessionPropertyValue(
              value,
              defaultValue,
              property.getName(),
              Optional.empty(),
              property.getName(),
              property.getDescription(),
              property.getSqlType().getDisplayName(),
              property.isHidden()));
    }

    for (Entry<String, ConnectorId> entry : new TreeMap<>(catalogs).entrySet()) {
      String catalog = entry.getKey();
      ConnectorId connectorId = entry.getValue();
      Map<String, String> connectorProperties = session.getConnectorProperties(connectorId);

      for (PropertyMetadata<?> property :
          new TreeMap<>(connectorSessionProperties.get(connectorId)).values()) {
        String defaultValue = firstNonNull(property.getDefaultValue(), "").toString();
        String value = connectorProperties.getOrDefault(property.getName(), defaultValue);

        sessionPropertyValues.add(
            new SessionPropertyValue(
                value,
                defaultValue,
                catalog + "." + property.getName(),
                Optional.of(catalog),
                property.getName(),
                property.getDescription(),
                property.getSqlType().getDisplayName(),
                property.isHidden()));
      }
    }

    return sessionPropertyValues.build();
  }
    private SessionProperty(Optional<String> catalogName, PropertyMetadata<T> propertyMetadata) {
      this.catalogName = catalogName;
      this.propertyName = propertyMetadata.getName();

      String fullName = propertyMetadata.getName();
      if (catalogName.isPresent()) {
        fullName = catalogName.get() + "." + fullName;
      }

      this.propertyMetadata =
          new PropertyMetadata<>(
              fullName,
              propertyMetadata.getDescription(),
              propertyMetadata.getSqlType(),
              propertyMetadata.getJavaType(),
              propertyMetadata.getDefaultValue(),
              propertyMetadata.isHidden(),
              propertyMetadata::decode);
    }