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.function.FunctionUtils; 032import gov.nist.secauto.metaschema.core.metapath.function.IArgument; 033import gov.nist.secauto.metaschema.core.metapath.function.IFunction; 034import gov.nist.secauto.metaschema.core.metapath.function.IFunctionExecutor; 035import gov.nist.secauto.metaschema.core.metapath.item.IItem; 036import gov.nist.secauto.metaschema.core.metapath.item.atomic.IAnyAtomicItem; 037import gov.nist.secauto.metaschema.core.util.ObjectUtils; 038 039import java.net.URI; 040import java.util.List; 041 042import edu.umd.cs.findbugs.annotations.NonNull; 043 044public final class CastFunction<ITEM extends IAnyAtomicItem> implements IFunctionExecutor { 045 @NonNull 046 private final ICastExecutor<ITEM> castExecutor; 047 048 @NonNull 049 static <ITEM extends IAnyAtomicItem> IFunction signature( 050 @NonNull URI namespace, 051 @NonNull String name, 052 @NonNull Class<ITEM> resulingAtomicType, 053 @NonNull ICastExecutor<ITEM> executor) { 054 return signature( 055 ObjectUtils.notNull(namespace.toASCIIString()), 056 name, 057 resulingAtomicType, 058 executor); 059 } 060 061 @NonNull 062 static <ITEM extends IAnyAtomicItem> IFunction signature( 063 @NonNull String namespace, 064 @NonNull String name, 065 @NonNull Class<ITEM> resulingAtomicType, 066 @NonNull ICastExecutor<ITEM> executor) { 067 return IFunction.builder() 068 .name(name) 069 .namespace(namespace) 070 .argument(IArgument.newBuilder() 071 .name("arg1") 072 .type(IAnyAtomicItem.class) 073 .zeroOrOne() 074 .build()) 075 .returnType(resulingAtomicType) 076 .returnZeroOrOne() 077 .functionHandler(newCastExecutor(executor)) 078 .build(); 079 } 080 081 @NonNull 082 private static <ITEM extends IAnyAtomicItem> CastFunction<ITEM> 083 newCastExecutor(@NonNull ICastExecutor<ITEM> executor) { 084 return new CastFunction<>(executor); 085 } 086 087 private CastFunction(@NonNull ICastExecutor<ITEM> castExecutor) { 088 this.castExecutor = castExecutor; 089 } 090 091 @Override 092 public ISequence<ITEM> execute(@NonNull IFunction function, 093 @NonNull List<ISequence<?>> arguments, 094 @NonNull DynamicContext dynamicContext, 095 IItem focus) { 096 097 ISequence<? extends IAnyAtomicItem> arg = FunctionUtils.asType( 098 ObjectUtils.notNull(arguments.get(0))); 099 100 IAnyAtomicItem item = FunctionUtils.getFirstItem(arg, true); 101 if (item == null) { 102 return ISequence.empty(); // NOPMD - readability 103 } 104 105 ITEM castItem = castExecutor.cast(item); 106 return ISequence.of(castItem); 107 } 108 109 @FunctionalInterface 110 public interface ICastExecutor<ITEM extends IAnyAtomicItem> { 111 /** 112 * Cast the provided {@code item}. 113 * 114 * @param item 115 * the item to cast 116 * @return the item cast to the appropriate type 117 */ 118 @NonNull 119 ITEM cast(@NonNull IAnyAtomicItem item); 120 } 121}