public void addSystemSessionProperty(PropertyMetadata<?> sessionProperty) {
   requireNonNull(sessionProperty, "sessionProperty is null");
   checkState(
       systemSessionProperties.put(sessionProperty.getName(), sessionProperty) == null,
       "System session property '%s' are already registered",
       sessionProperty.getName());
 }
 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 void validateSystemSessionProperty(String propertyName, String propertyValue) {
    PropertyMetadata<?> propertyMetadata =
        getSystemSessionPropertyMetadata(propertyName)
            .orElseThrow(
                () ->
                    new PrestoException(
                        INVALID_SESSION_PROPERTY, "Unknown session property " + propertyName));

    decodePropertyValue(
        propertyName, propertyValue, propertyMetadata.getJavaType(), propertyMetadata);
  }
  public void validateCatalogSessionProperty(
      ConnectorId connectorId, String catalogName, String propertyName, String propertyValue) {
    String fullPropertyName = catalogName + "." + propertyName;
    PropertyMetadata<?> propertyMetadata =
        getConnectorSessionPropertyMetadata(connectorId, propertyName)
            .orElseThrow(
                () ->
                    new PrestoException(
                        INVALID_SESSION_PROPERTY, "Unknown session property " + fullPropertyName));

    decodePropertyValue(
        fullPropertyName, propertyValue, propertyMetadata.getJavaType(), propertyMetadata);
  }
  public List<SessionPropertyValue> getAllSessionProperties(Session session) {
    requireNonNull(session, "session is null");

    List<SessionPropertyValue> properties = new ArrayList<>();
    for (SessionProperty<?> sessionProperty : allSessionProperties.values()) {
      PropertyMetadata<?> propertyMetadata = sessionProperty.getMetadata();
      String defaultValue = firstNonNull(propertyMetadata.getDefaultValue(), "").toString();

      Map<String, String> values;
      if (sessionProperty.getCatalogName().isPresent()) {
        values = session.getCatalogProperties(sessionProperty.getCatalogName().get());
      } else {
        values = session.getSystemProperties();
      }
      String value = values.getOrDefault(sessionProperty.getPropertyName(), defaultValue);

      properties.add(
          new SessionPropertyValue(
              value,
              defaultValue,
              sessionProperty.getFullyQualifiedName(),
              sessionProperty.getCatalogName(),
              sessionProperty.getPropertyName(),
              sessionProperty.getMetadata().getDescription(),
              sessionProperty.getMetadata().getSqlType().getTypeSignature().toString()));
    }

    // sort properties by catalog then property
    Collections.sort(
        properties,
        (left, right) ->
            ComparisonChain.start()
                .compare(
                    left.getCatalogName().orElse(null),
                    right.getCatalogName().orElse(null),
                    Ordering.natural().nullsFirst())
                .compare(left.getPropertyName(), right.getPropertyName())
                .result());

    return ImmutableList.copyOf(properties);
  }
  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);
    }
  }
    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);
    }
 public String getFullyQualifiedName() {
   return propertyMetadata.getName();
 }
  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();
  }