1
2
3
4
5
6 package gov.nist.secauto.oscal.lib.profile.resolver.policy;
7
8 import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter;
9 import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem;
10 import gov.nist.secauto.metaschema.core.util.CollectionUtil;
11 import gov.nist.secauto.metaschema.core.util.CustomCollectors;
12 import gov.nist.secauto.oscal.lib.model.Link;
13 import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem;
14
15 import org.apache.logging.log4j.LogManager;
16 import org.apache.logging.log4j.Logger;
17
18 import java.net.URI;
19 import java.util.List;
20 import java.util.Locale;
21
22 import edu.umd.cs.findbugs.annotations.NonNull;
23
24 public class LinkReferencePolicy
25 extends AbstractMultiItemTypeReferencePolicy<Link> {
26 private static final Logger LOGGER = LogManager.getLogger(LinkReferencePolicy.class);
27
28 @SuppressWarnings("null")
29 @NonNull
30 public static LinkReferencePolicy create(@NonNull IEntityItem.ItemType itemType) {
31 return create(List.of(itemType));
32 }
33
34 @NonNull
35 public static LinkReferencePolicy create(@NonNull List<IEntityItem.ItemType> itemTypes) {
36 return new LinkReferencePolicy(CollectionUtil.requireNonEmpty(itemTypes, "itemTypes"));
37 }
38
39 public LinkReferencePolicy(@NonNull List<IEntityItem.ItemType> itemTypes) {
40 super(IIdentifierParser.FRAGMENT_PARSER, itemTypes);
41 }
42
43 @Override
44 public String getReferenceText(@NonNull Link link) {
45 return link.getHref().toString();
46 }
47
48 @Override
49 public void setReferenceText(@NonNull Link link, @NonNull String newValue) {
50 link.setHref(URI.create(newValue));
51 }
52
53 @Override
54 protected void handleUnselected(
55 @NonNull IModelNodeItem<?, ?> contextItem,
56 @NonNull Link link,
57 @NonNull IEntityItem item,
58 @NonNull ReferenceCountingVisitor.Context visitorContext) {
59 URI linkHref = link.getHref();
60 URI sourceUri = item.getSource();
61
62 URI resolved = sourceUri.resolve(linkHref);
63 if (LOGGER.isTraceEnabled()) {
64 LOGGER.atTrace().log("At path '{}', remapping orphaned URI '{}' to '{}'",
65 contextItem.toPath(IPathFormatter.METAPATH_PATH_FORMATER),
66 linkHref.toString(),
67 resolved.toString());
68 }
69 link.setHref(resolved);
70 }
71
72 @Override
73 protected boolean handleIndexMiss(
74 @NonNull IModelNodeItem<?, ?> contextItem,
75 @NonNull Link link,
76 @NonNull List<IEntityItem.ItemType> itemTypes,
77 @NonNull String identifier,
78 @NonNull ReferenceCountingVisitor.Context visitorContext) {
79 if (LOGGER.isWarnEnabled()) {
80 LOGGER.atWarn().log(
81 "The link at '{}' with rel '{}' should reference a {} identified by '{}'."
82 + " The index did not contain the identifier.",
83 contextItem.toPath(IPathFormatter.METAPATH_PATH_FORMATER),
84 link.getRel(),
85 itemTypes.stream()
86 .map(en -> en.name().toLowerCase(Locale.ROOT))
87 .collect(CustomCollectors.joiningWithOxfordComma("or")),
88 identifier);
89 }
90 return true;
91 }
92
93 @Override
94 protected boolean handleIdentifierNonMatch(
95 @NonNull IModelNodeItem<?, ?> contextItem,
96 @NonNull Link reference,
97 @NonNull ReferenceCountingVisitor.Context visitorContext) {
98 if (LOGGER.isDebugEnabled()) {
99 LOGGER.atDebug().log("Ignoring URI '{}' at '{}'",
100 reference.getHref().toString(),
101 contextItem.toPath(IPathFormatter.METAPATH_PATH_FORMATER));
102 }
103
104 return true;
105 }
106 }