1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.oscal.lib;
7   
8   import gov.nist.secauto.metaschema.core.util.ObjectUtils;
9   import gov.nist.secauto.oscal.lib.model.BackMatter.Resource;
10  import gov.nist.secauto.oscal.lib.model.BackMatter.Resource.Rlink;
11  
12  import java.net.URI;
13  import java.util.List;
14  import java.util.regex.Matcher;
15  import java.util.regex.Pattern;
16  
17  import edu.umd.cs.findbugs.annotations.NonNull;
18  import edu.umd.cs.findbugs.annotations.Nullable;
19  
20  public final class OscalUtils {
21    private static final Pattern INTERNAL_REFERENCE_FRAGMENT_PATTERN = Pattern.compile("^#(.+)$");
22  
23    private OscalUtils() {
24      // disable construction
25    }
26  
27    @SuppressWarnings("PMD.OnlyOneReturn") // readability
28    public static boolean isInternalReference(@NonNull URI uri) {
29      if (uri.isAbsolute()) {
30        return false;
31      }
32  
33      String schemeSpecificPart = uri.getSchemeSpecificPart();
34      return uri.getScheme() == null && (schemeSpecificPart == null || schemeSpecificPart.isEmpty())
35          && uri.getFragment() != null;
36    }
37  
38    /**
39     * Get the id based on a URI's fragment.
40     *
41     * @param fragment
42     *          the URI to extract the identifier from
43     * @return the identifier
44     * @throws IllegalArgumentException
45     *           if the fragment does not contain an identifier
46     */
47    @NonNull
48    public static String internalReferenceFragmentToId(@NonNull URI fragment) {
49      return internalReferenceFragmentToId(ObjectUtils.notNull(fragment.toString()));
50    }
51  
52    /**
53     * Get the id based on a URI's fragment.
54     *
55     * @param fragment
56     *          the URI to extract the identifier from
57     * @return the identifier
58     * @throws IllegalArgumentException
59     *           if the fragment does not contain an identifier
60     */
61    @NonNull
62    public static String internalReferenceFragmentToId(@NonNull String fragment) {
63      Matcher matcher = INTERNAL_REFERENCE_FRAGMENT_PATTERN.matcher(fragment);
64      String retval;
65      if (matcher.matches()) {
66        retval = ObjectUtils.notNull(matcher.group(1));
67      } else {
68        throw new IllegalArgumentException(String.format("The fragment '%s' does not match the pattern '%s'", fragment,
69            INTERNAL_REFERENCE_FRAGMENT_PATTERN.pattern()));
70      }
71      return retval;
72    }
73  
74    @Nullable
75    public static Rlink findMatchingRLink(@NonNull Resource resource, @Nullable String preferredMediaType) {
76      // find a suitable rlink reference
77      List<Rlink> rlinks = resource.getRlinks();
78  
79      Rlink retval = null;
80      if (rlinks != null) {
81        // check if there is a matching rlink for the mime type
82        if (preferredMediaType != null) {
83          // find preferred mime type first
84          retval = rlinks.stream().filter(rlink -> preferredMediaType.equals(rlink.getMediaType())).findFirst()
85              .orElse(null);
86        } else {
87          // use the first one instead
88          retval = rlinks.stream().findFirst().orElse(null);
89        }
90      }
91      return retval;
92    }
93  }