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.DocumentFunctionException; 033import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; 034import gov.nist.secauto.metaschema.core.metapath.function.IArgument; 035import gov.nist.secauto.metaschema.core.metapath.function.IFunction; 036import gov.nist.secauto.metaschema.core.metapath.item.IItem; 037import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem; 038import gov.nist.secauto.metaschema.core.metapath.item.node.IDocumentNodeItem; 039import gov.nist.secauto.metaschema.core.util.ObjectUtils; 040 041import java.io.IOException; 042import java.net.URI; 043import java.util.List; 044 045import edu.umd.cs.findbugs.annotations.NonNull; 046 047public final class FnDoc { 048 // private static final Logger logger = LogManager.getLogger(FnDoc.class); 049 050 @NonNull 051 static final IFunction SIGNATURE = IFunction.builder() 052 .name("doc") 053 .namespace(MetapathConstants.NS_XPATH_FUNCTIONS) 054 .deterministic() 055 .contextDependent() 056 .focusIndependent() 057 .argument(IArgument.newBuilder() 058 .name("arg1") 059 .type(IStringItem.class) 060 .zeroOrOne() 061 .build()) 062 .returnType(IDocumentNodeItem.class) 063 .returnOne() 064 .functionHandler(FnDoc::execute) 065 .build(); 066 067 private FnDoc() { 068 // disable construction 069 } 070 071 @SuppressWarnings("unused") 072 @NonNull 073 private static ISequence<IDocumentNodeItem> execute(@NonNull IFunction function, 074 @NonNull List<ISequence<?>> arguments, @NonNull DynamicContext dynamicContext, 075 IItem focus) { 076 ISequence<? extends IStringItem> arg = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(0))); 077 078 IStringItem item = FunctionUtils.getFirstItem(arg, true); 079 080 return item == null ? ISequence.empty() : ISequence.of(fnDoc(item, dynamicContext)); 081 } 082 083 /** 084 * Dynamically load the document associated with the URI, and return a 085 * {@link IDocumentNodeItem} containing the result. 086 * <p> 087 * Based on the XPath 3.1 088 * <a href="https://www.w3.org/TR/xpath-functions-31/#func-doc">fn:doc</a> 089 * function. 090 * 091 * @param uri 092 * the resource to load the data from 093 * @param context 094 * the Metapath dynamic context 095 * @return the loaded document node item 096 */ 097 public static IDocumentNodeItem fnDoc(@NonNull IStringItem uri, @NonNull DynamicContext context) { 098 URI documentUri; 099 try { 100 documentUri = URI.create(uri.asString()); 101 } catch (IllegalArgumentException ex) { 102 throw new DocumentFunctionException(DocumentFunctionException.INVALID_ARGUMENT, 103 String.format("Invalid URI argument '%s' to fn:doc or fn:doc-available.", uri.asString()), ex); 104 } 105 106 URI baseUri = context.getStaticContext().getBaseUri(); 107 if (baseUri != null) { 108 // resolve if possible 109 documentUri = baseUri.resolve(documentUri); 110 } else { 111 if (!documentUri.isAbsolute() && !documentUri.isOpaque()) { 112 throw new DocumentFunctionException(DocumentFunctionException.ERROR_RETRIEVING_RESOURCE, String 113 .format("No base-uri is available in the static context to resolve the URI '%s'.", documentUri.toString())); 114 } 115 } 116 117 try { 118 return context.getDocumentLoader().loadAsNodeItem(ObjectUtils.notNull(documentUri)); 119 } catch (IOException ex) { 120 throw new DocumentFunctionException(DocumentFunctionException.ERROR_RETRIEVING_RESOURCE, String 121 .format("Unable to retrieve the resource identified by the URI '%s'.", documentUri.toString()), ex); 122 } 123 } 124}