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