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