1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.oscal.lib.profile.resolver.policy;
7   
8   import com.vladsch.flexmark.util.sequence.BasedSequence;
9   
10  import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension;
11  import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode;
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.CollectionUtil;
15  import gov.nist.secauto.metaschema.core.util.CustomCollectors;
16  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
17  import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem;
18  
19  import org.apache.logging.log4j.LogManager;
20  import org.apache.logging.log4j.Logger;
21  
22  import java.util.List;
23  import java.util.Locale;
24  
25  import edu.umd.cs.findbugs.annotations.NonNull;
26  
27  public class InsertReferencePolicy
28      extends AbstractCustomReferencePolicy<InsertAnchorNode> {
29    private static final Logger LOGGER = LogManager.getLogger(InsertReferencePolicy.class);
30  
31    public InsertReferencePolicy() {
32      super(IIdentifierParser.IDENTITY_PARSER);
33    }
34  
35    @Override
36    protected List<IEntityItem.ItemType> getEntityItemTypes(@NonNull InsertAnchorExtension.InsertAnchorNode insert) {
37      String type = insert.getType().toString();
38  
39      if (!"param".equals(type)) {
40        throw new UnsupportedOperationException("unrecognized insert type: " + type);
41      }
42      return CollectionUtil.singletonList(IEntityItem.ItemType.PARAMETER);
43    }
44  
45    @Override
46    public String getReferenceText(@NonNull InsertAnchorExtension.InsertAnchorNode insert) {
47      return insert.getIdReference().toString();
48    }
49  
50    @Override
51    public void setReferenceText(@NonNull InsertAnchorExtension.InsertAnchorNode insert, @NonNull String newReference) {
52      insert.setIdReference(ObjectUtils.notNull(BasedSequence.of(newReference)));
53    }
54  
55    @Override
56    protected boolean handleIndexMiss(
57        @NonNull IModelNodeItem<?, ?> contextItem,
58        @NonNull InsertAnchorExtension.InsertAnchorNode insert,
59        @NonNull List<IEntityItem.ItemType> itemTypes,
60        @NonNull String identifier,
61        @NonNull ReferenceCountingVisitor.Context visitorContext) {
62      if (LOGGER.isErrorEnabled()) {
63        LOGGER.atError().log(
64            "The '{}' insert at '{}' should reference a '{}' identified by '{}'."
65                + " The index did not contain the identifier.",
66            insert.getType().toString(),
67            contextItem.toPath(IPathFormatter.METAPATH_PATH_FORMATER),
68            itemTypes.stream()
69                .map(type -> type.name().toLowerCase(Locale.ROOT))
70                .collect(CustomCollectors.joiningWithOxfordComma("or")),
71            identifier);
72      }
73      return true;
74    }
75  
76  }