2222import java .io .IOException ;
2323import java .io .InputStream ;
2424import java .io .UncheckedIOException ;
25+ import java .util .Collections ;
26+ import java .util .HashMap ;
2527import java .util .List ;
2628import java .util .Map ;
2729import java .util .Optional ;
@@ -276,6 +278,8 @@ public String description() {
276278
277279 public abstract Map <String , Option > options ();
278280
281+ public abstract Optional <Map <String , Object >> metadata ();
282+
279283 public List <Argument > requiredArguments () {
280284 return requiredArgsSupplier .get ();
281285 }
@@ -381,25 +385,29 @@ public abstract static class ScalarFunction {
381385 @ Nullable
382386 public abstract String description ();
383387
388+ public abstract Optional <Map <String , Object >> metadata ();
389+
384390 public abstract List <ScalarFunctionVariant > impls ();
385391
386392 public Stream <ScalarFunctionVariant > resolve (String urn ) {
387- return impls ().stream ().map (f -> f .resolve (urn , name (), description ()));
393+ return impls ().stream ().map (f -> f .resolve (urn , name (), description (), metadata () ));
388394 }
389395 }
390396
391397 @ JsonDeserialize (as = ImmutableSimpleExtension .ScalarFunctionVariant .class )
392398 @ JsonSerialize (as = ImmutableSimpleExtension .ScalarFunctionVariant .class )
393399 @ Value .Immutable
394400 public abstract static class ScalarFunctionVariant extends Function {
395- public ScalarFunctionVariant resolve (String urn , String name , String description ) {
401+ public ScalarFunctionVariant resolve (
402+ String urn , String name , String description , Optional <Map <String , Object >> metadata ) {
396403 return ImmutableSimpleExtension .ScalarFunctionVariant .builder ()
397404 .urn (urn )
398405 .name (name )
399406 .description (description )
400407 .nullability (nullability ())
401408 .args (args ())
402409 .options (options ())
410+ .metadata (metadata )
403411 .ordered (ordered ())
404412 .variadic (variadic ())
405413 .returnType (returnType ())
@@ -417,10 +425,12 @@ public abstract static class AggregateFunction {
417425 @ Nullable
418426 public abstract String description ();
419427
428+ public abstract Optional <Map <String , Object >> metadata ();
429+
420430 public abstract List <AggregateFunctionVariant > impls ();
421431
422432 public Stream <AggregateFunctionVariant > resolve (String urn ) {
423- return impls ().stream ().map (f -> f .resolve (urn , name (), description ()));
433+ return impls ().stream ().map (f -> f .resolve (urn , name (), description (), metadata () ));
424434 }
425435 }
426436
@@ -434,10 +444,12 @@ public abstract static class WindowFunction {
434444 @ Nullable
435445 public abstract String description ();
436446
447+ public abstract Optional <Map <String , Object >> metadata ();
448+
437449 public abstract List <WindowFunctionVariant > impls ();
438450
439451 public Stream <WindowFunctionVariant > resolve (String urn ) {
440- return impls ().stream ().map (f -> f .resolve (urn , name (), description ()));
452+ return impls ().stream ().map (f -> f .resolve (urn , name (), description (), metadata () ));
441453 }
442454
443455 public static ImmutableSimpleExtension .WindowFunction .Builder builder () {
@@ -463,14 +475,16 @@ public String toString() {
463475 @ Nullable
464476 public abstract TypeExpression intermediate ();
465477
466- AggregateFunctionVariant resolve (String urn , String name , String description ) {
478+ AggregateFunctionVariant resolve (
479+ String urn , String name , String description , Optional <Map <String , Object >> metadata ) {
467480 return ImmutableSimpleExtension .AggregateFunctionVariant .builder ()
468481 .urn (urn )
469482 .name (name )
470483 .description (description )
471484 .nullability (nullability ())
472485 .args (args ())
473486 .options (options ())
487+ .metadata (metadata )
474488 .ordered (ordered ())
475489 .variadic (variadic ())
476490 .decomposability (decomposability ())
@@ -505,14 +519,16 @@ public String toString() {
505519 return super .toString ();
506520 }
507521
508- WindowFunctionVariant resolve (String urn , String name , String description ) {
522+ WindowFunctionVariant resolve (
523+ String urn , String name , String description , Optional <Map <String , Object >> metadata ) {
509524 return ImmutableSimpleExtension .WindowFunctionVariant .builder ()
510525 .urn (urn )
511526 .name (name )
512527 .description (description )
513528 .nullability (nullability ())
514529 .args (args ())
515530 .options (options ())
531+ .metadata (metadata )
516532 .ordered (ordered ())
517533 .variadic (variadic ())
518534 .decomposability (decomposability ())
@@ -549,6 +565,8 @@ public abstract static class Type {
549565
550566 protected abstract Optional <Boolean > variadic ();
551567
568+ public abstract Optional <Map <String , Object >> metadata ();
569+
552570 public TypeAnchor getAnchor () {
553571 return anchorSupplier .get ();
554572 }
@@ -574,6 +592,9 @@ public abstract static class ExtensionSignatures {
574592 @ JsonProperty ("window_functions" )
575593 public abstract List <WindowFunction > windows ();
576594
595+ @ JsonProperty ("metadata" )
596+ public abstract Optional <Map <String , Object >> metadata ();
597+
577598 public int size () {
578599 return (types () == null ? 0 : types ().size ())
579600 + (scalars () == null ? 0 : scalars ().size ())
@@ -643,6 +664,11 @@ BidiMap<String, String> uriUrnMap() {
643664 return new BidiMap <>();
644665 }
645666
667+ @ Value .Default
668+ public Map <String , Map <String , Object >> extensionMetadata () {
669+ return Collections .emptyMap ();
670+ }
671+
646672 public abstract List <Type > types ();
647673
648674 public abstract List <ScalarFunctionVariant > scalarFunctions ();
@@ -655,6 +681,16 @@ public static ImmutableSimpleExtension.ExtensionCollection.Builder builder() {
655681 return ImmutableSimpleExtension .ExtensionCollection .builder ();
656682 }
657683
684+ /**
685+ * Gets the top-level metadata for a specific extension by URN.
686+ *
687+ * @param urn The URN of the extension
688+ * @return The metadata map if present, empty Optional otherwise
689+ */
690+ public Optional <Map <String , Object >> getExtensionMetadata (String urn ) {
691+ return Optional .ofNullable (extensionMetadata ().get (urn ));
692+ }
693+
658694 public Type getType (TypeAnchor anchor ) {
659695 Type type = typeLookup .get ().get (anchor );
660696 if (type != null ) {
@@ -744,6 +780,10 @@ public ExtensionCollection merge(ExtensionCollection extensionCollection) {
744780 mergedUriUrnMap .merge (uriUrnMap ());
745781 mergedUriUrnMap .merge (extensionCollection .uriUrnMap ());
746782
783+ Map <String , Map <String , Object >> mergedExtensionMetadata = new HashMap <>();
784+ mergedExtensionMetadata .putAll (extensionMetadata ());
785+ mergedExtensionMetadata .putAll (extensionCollection .extensionMetadata ());
786+
747787 return ImmutableSimpleExtension .ExtensionCollection .builder ()
748788 .addAllAggregateFunctions (aggregateFunctions ())
749789 .addAllAggregateFunctions (extensionCollection .aggregateFunctions ())
@@ -754,6 +794,7 @@ public ExtensionCollection merge(ExtensionCollection extensionCollection) {
754794 .addAllTypes (types ())
755795 .addAllTypes (extensionCollection .types ())
756796 .uriUrnMap (mergedUriUrnMap )
797+ .extensionMetadata (mergedExtensionMetadata )
757798 .build ();
758799 }
759800 }
@@ -859,13 +900,17 @@ public static ExtensionCollection buildExtensionCollection(
859900 BidiMap <String , String > uriUrnMap = new BidiMap <>();
860901 uriUrnMap .put (uri , urn );
861902
903+ Map <String , Map <String , Object >> extMetadata = new HashMap <>();
904+ extensionSignatures .metadata ().ifPresent (m -> extMetadata .put (urn , m ));
905+
862906 ImmutableSimpleExtension .ExtensionCollection collection =
863907 ImmutableSimpleExtension .ExtensionCollection .builder ()
864908 .scalarFunctions (scalarFunctionVariants )
865909 .aggregateFunctions (aggregateFunctionVariants )
866910 .windowFunctions (allWindowFunctionVariants )
867911 .addAllTypes (extensionSignatures .types ())
868912 .uriUrnMap (uriUrnMap )
913+ .extensionMetadata (extMetadata )
869914 .build ();
870915
871916 LOGGER .atDebug ().log (
0 commit comments