001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package dev.metaschema.oscal.lib; 007 008import java.net.URI; 009import java.util.List; 010import java.util.regex.Matcher; 011import java.util.regex.Pattern; 012 013import dev.metaschema.core.util.ObjectUtils; 014import dev.metaschema.oscal.lib.model.BackMatter.Resource; 015import dev.metaschema.oscal.lib.model.BackMatter.Resource.Rlink; 016import edu.umd.cs.findbugs.annotations.NonNull; 017import edu.umd.cs.findbugs.annotations.Nullable; 018 019public final class OscalUtils { 020 private static final Pattern INTERNAL_REFERENCE_FRAGMENT_PATTERN = Pattern.compile("^#(.+)$"); 021 022 private OscalUtils() { 023 // disable construction 024 } 025 026 @SuppressWarnings("PMD.OnlyOneReturn") // readability 027 public static boolean isInternalReference(@NonNull URI uri) { 028 if (uri.isAbsolute()) { 029 return false; 030 } 031 032 String schemeSpecificPart = uri.getSchemeSpecificPart(); 033 return uri.getScheme() == null && (schemeSpecificPart == null || schemeSpecificPart.isEmpty()) 034 && uri.getFragment() != null; 035 } 036 037 /** 038 * Get the id based on a URI's fragment. 039 * 040 * @param fragment 041 * the URI to extract the identifier from 042 * @return the identifier 043 * @throws IllegalArgumentException 044 * if the fragment does not contain an identifier 045 */ 046 @NonNull 047 public static String internalReferenceFragmentToId(@NonNull URI fragment) { 048 return internalReferenceFragmentToId(ObjectUtils.notNull(fragment.toString())); 049 } 050 051 /** 052 * Get the id based on a URI's fragment. 053 * 054 * @param fragment 055 * the URI to extract the identifier from 056 * @return the identifier 057 * @throws IllegalArgumentException 058 * if the fragment does not contain an identifier 059 */ 060 @NonNull 061 public static String internalReferenceFragmentToId(@NonNull String fragment) { 062 Matcher matcher = INTERNAL_REFERENCE_FRAGMENT_PATTERN.matcher(fragment); 063 String retval; 064 if (matcher.matches()) { 065 retval = ObjectUtils.notNull(matcher.group(1)); 066 } else { 067 throw new IllegalArgumentException(String.format("The fragment '%s' does not match the pattern '%s'", fragment, 068 INTERNAL_REFERENCE_FRAGMENT_PATTERN.pattern())); 069 } 070 return retval; 071 } 072 073 @Nullable 074 public static Rlink findMatchingRLink(@NonNull Resource resource, @Nullable String preferredMediaType) { 075 // find a suitable rlink reference 076 List<Rlink> rlinks = resource.getRlinks(); 077 078 Rlink retval = null; 079 if (rlinks != null) { 080 // check if there is a matching rlink for the mime type 081 if (preferredMediaType != null) { 082 // find preferred mime type first 083 retval = rlinks.stream().filter(rlink -> preferredMediaType.equals(rlink.getMediaType())).findFirst() 084 .orElse(null); 085 } else { 086 // use the first one instead 087 retval = rlinks.stream().findFirst().orElse(null); 088 } 089 } 090 return retval; 091 } 092}