001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package gov.nist.secauto.oscal.lib.metapath.function.library; 007 008import gov.nist.secauto.metaschema.core.metapath.DynamicContext; 009import gov.nist.secauto.metaschema.core.metapath.ISequence; 010import gov.nist.secauto.metaschema.core.metapath.MetapathConstants; 011import gov.nist.secauto.metaschema.core.metapath.MetapathException; 012import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; 013import gov.nist.secauto.metaschema.core.metapath.function.IArgument; 014import gov.nist.secauto.metaschema.core.metapath.function.IFunction; 015import gov.nist.secauto.metaschema.core.metapath.item.IItem; 016import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; 017import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; 018import gov.nist.secauto.metaschema.core.util.ObjectUtils; 019import gov.nist.secauto.oscal.lib.OscalModelConstants; 020import gov.nist.secauto.oscal.lib.model.Catalog; 021import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolutionException; 022import gov.nist.secauto.oscal.lib.profile.resolver.ProfileResolver; 023 024import java.io.IOException; 025import java.util.List; 026 027import edu.umd.cs.findbugs.annotations.NonNull; 028 029public final class ResolveProfile { 030 031 @NonNull 032 static final IFunction SIGNATURE_NO_ARG = IFunction.builder() 033 .name("resolve-profile") 034 .namespace(OscalModelConstants.NS_OSCAL) 035 .returnType(INodeItem.type()) 036 .focusDependent() 037 .contextDependent() 038 .deterministic() 039 .returnOne() 040 .functionHandler(ResolveProfile::executeNoArg) 041 .build(); 042 043 @NonNull 044 static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() 045 .name("resolve-profile") 046 .namespace(OscalModelConstants.NS_OSCAL) 047 .argument(IArgument.builder() 048 .name("profile") 049 .type(INodeItem.type()) 050 .zeroOrOne() 051 .build()) 052 .focusDependent() 053 .contextDependent() 054 .deterministic() 055 .returnType(INodeItem.type()) 056 .returnOne() 057 .functionHandler(ResolveProfile::executeOneArg) 058 .build(); 059 060 @NonNull 061 static final IFunction SIGNATURE_NO_ARG_METAPATH = IFunction.builder() 062 .name("resolve-profile") 063 .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) 064 .returnType(INodeItem.type()) 065 .focusDependent() 066 .contextDependent() 067 .deterministic() 068 .returnOne() 069 .functionHandler(ResolveProfile::executeNoArg) 070 .build(); 071 072 @NonNull 073 static final IFunction SIGNATURE_ONE_ARG_METAPATH = IFunction.builder() 074 .name("resolve-profile") 075 .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS) 076 .argument(IArgument.builder() 077 .name("profile") 078 .type(INodeItem.type()) 079 .zeroOrOne() 080 .build()) 081 .focusDependent() 082 .contextDependent() 083 .deterministic() 084 .returnType(INodeItem.type()) 085 .returnOne() 086 .functionHandler(ResolveProfile::executeOneArg) 087 .build(); 088 089 private ResolveProfile() { 090 // disable construction 091 } 092 093 @SuppressWarnings({ "unused", 094 "PMD.OnlyOneReturn" // readability 095 }) 096 @NonNull 097 public static ISequence<?> executeNoArg( 098 @NonNull IFunction function, 099 @NonNull List<ISequence<?>> arguments, 100 @NonNull DynamicContext dynamicContext, 101 IItem focus) { 102 103 if (focus == null) { 104 return ISequence.empty(); 105 } 106 return ISequence.of(resolveProfile(FunctionUtils.asType(focus), dynamicContext)); 107 } 108 109 @SuppressWarnings({ "unused", 110 "PMD.OnlyOneReturn" // readability 111 }) 112 @NonNull 113 public static ISequence<?> executeOneArg( 114 @NonNull IFunction function, 115 @NonNull List<ISequence<?>> arguments, 116 @NonNull DynamicContext dynamicContext, 117 IItem focus) { 118 ISequence<? extends IDocumentNodeItem> arg = FunctionUtils.asType( 119 ObjectUtils.notNull(arguments.get(0))); 120 121 IItem item = arg.getFirstItem(true); 122 if (item == null) { 123 return ISequence.empty(); 124 } 125 126 return ISequence.of(resolveProfile(FunctionUtils.asType(item), dynamicContext)); 127 } 128 129 @NonNull 130 public static IDocumentNodeItem resolveProfile( 131 @NonNull IDocumentNodeItem profile, 132 @NonNull DynamicContext dynamicContext) { 133 Object profileObject = INodeItem.toValue(profile); 134 135 IDocumentNodeItem retval; 136 if (profileObject instanceof Catalog) { 137 retval = profile; 138 } else { 139 // this is a profile 140 ProfileResolver resolver = new ProfileResolver(dynamicContext); 141 try { 142 retval = resolver.resolve(profile); 143 } catch (IOException | ProfileResolutionException ex) { 144 throw new MetapathException(String.format("Fun: Unable to resolve profile '%s'", profile.getBaseUri()), ex); 145 } 146 } 147 return retval; 148 } 149}