001/* 002 * Portions of this software was developed by employees of the National Institute 003 * of Standards and Technology (NIST), an agency of the Federal Government and is 004 * being made available as a public service. Pursuant to title 17 United States 005 * Code Section 105, works of NIST employees are not subject to copyright 006 * protection in the United States. This software may be subject to foreign 007 * copyright. Permission in the United States and in foreign countries, to the 008 * extent that NIST may hold copyright, to use, copy, modify, create derivative 009 * works, and distribute this software and its documentation without fee is hereby 010 * granted on a non-exclusive basis, provided that this notice and disclaimer 011 * of warranty appears in all copies. 012 * 013 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER 014 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY 015 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF 016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM 017 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE 018 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT 019 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, 020 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, 021 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, 022 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR 023 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT 024 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. 025 */ 026 027package gov.nist.secauto.metaschema.core.metapath.function.library; 028 029import gov.nist.secauto.metaschema.core.metapath.DynamicContext; 030import gov.nist.secauto.metaschema.core.metapath.ISequence; 031import gov.nist.secauto.metaschema.core.metapath.MetapathConstants; 032import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; 033import gov.nist.secauto.metaschema.core.metapath.function.IArgument; 034import gov.nist.secauto.metaschema.core.metapath.function.IFunction; 035import gov.nist.secauto.metaschema.core.metapath.item.IItem; 036import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyUriItem; 037import gov.nist.secauto.metaschema.core.metapath.item.node.INodeItem; 038import gov.nist.secauto.metaschema.core.util.ObjectUtils; 039 040import java.net.URI; 041import java.util.List; 042 043import edu.umd.cs.findbugs.annotations.NonNull; 044import edu.umd.cs.findbugs.annotations.Nullable; 045 046/** 047 * Since a node doesn't have a base URI in Metaschema, this is an alias for the 048 * document-uri function. 049 */ 050public final class FnBaseUri { 051 052 @NonNull 053 static final IFunction SIGNATURE_NO_ARG = IFunction.builder() 054 .name("base-uri") 055 .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) 056 .deterministic() 057 .contextDependent() 058 .focusDependent() 059 .returnType(IAnyUriItem.class) 060 .returnOne() 061 .functionHandler(FnBaseUri::executeNoArg) 062 .build(); 063 064 @NonNull 065 static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() 066 .name("base-uri") 067 .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) 068 .deterministic() 069 .contextIndependent() 070 .focusIndependent() 071 .argument(IArgument.newBuilder() 072 .name("arg1") 073 .type(INodeItem.class) 074 .zeroOrOne() 075 .build()) 076 .returnType(IAnyUriItem.class) 077 .returnOne() 078 .functionHandler(FnBaseUri::executeOneArg) 079 .build(); 080 081 private FnBaseUri() { 082 // disable construction 083 } 084 085 @SuppressWarnings("unused") 086 @NonNull 087 private static ISequence<IAnyUriItem> executeNoArg(@NonNull IFunction function, 088 @NonNull List<ISequence<?>> arguments, 089 @NonNull DynamicContext dynamicContext, 090 IItem focus) { 091 return ISequence.of(fnBaseUri( 092 FunctionUtils.requireTypeOrNull(INodeItem.class, focus))); 093 } 094 095 @SuppressWarnings("unused") 096 @NonNull 097 private static ISequence<IAnyUriItem> executeOneArg(@NonNull IFunction function, 098 @NonNull List<ISequence<?>> arguments, 099 @NonNull DynamicContext dynamicContext, 100 IItem focus) { 101 102 ISequence<? extends INodeItem> arg = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(0))); 103 104 INodeItem item = FunctionUtils.getFirstItem(arg, true); 105 106 return ISequence.of(fnBaseUri(item)); 107 } 108 109 /** 110 * Get the base URI for the provided {@code nodeItem}. 111 * <p> 112 * Based on the XPath 3.1 <a href= 113 * "https://www.w3.org/TR/xpath-functions-31/#func-base-uri">fn:base-uri</a> 114 * function. 115 * 116 * @param nodeItem 117 * the node to get the base URI from 118 * @return the base URI, or {@code null} if the node is either null or doesn't 119 * have a base URI 120 */ 121 @SuppressWarnings("PMD.NullAssignment") // for readability 122 @Nullable 123 public static IAnyUriItem fnBaseUri(INodeItem nodeItem) { 124 IAnyUriItem retval; 125 if (nodeItem == null) { 126 retval = null; // NOPMD - intentional 127 } else { 128 URI baseUri = nodeItem.getBaseUri(); 129 retval = baseUri == null ? null : IAnyUriItem.valueOf(baseUri); 130 } 131 return retval; 132 } 133}