001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package gov.nist.secauto.oscal.lib.profile.resolver.policy;
007
008import com.vladsch.flexmark.util.sequence.BasedSequence;
009
010import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode;
011import gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter;
012import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem;
013import gov.nist.secauto.metaschema.core.util.CollectionUtil;
014import gov.nist.secauto.metaschema.core.util.CustomCollectors;
015import gov.nist.secauto.metaschema.core.util.ObjectUtils;
016import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem;
017
018import org.apache.logging.log4j.LogManager;
019import org.apache.logging.log4j.Logger;
020
021import java.util.List;
022import java.util.Locale;
023
024import edu.umd.cs.findbugs.annotations.NonNull;
025
026public class InsertReferencePolicy
027    extends AbstractCustomReferencePolicy<InsertAnchorNode> {
028  private static final Logger LOGGER = LogManager.getLogger(InsertReferencePolicy.class);
029
030  public InsertReferencePolicy() {
031    super(IIdentifierParser.IDENTITY_PARSER);
032  }
033
034  @Override
035  protected List<IEntityItem.ItemType> getEntityItemTypes(@NonNull InsertAnchorNode insert) {
036    String type = insert.getType().toString();
037
038    if (!"param".equals(type)) {
039      throw new UnsupportedOperationException("unrecognized insert type: " + type);
040    }
041    return CollectionUtil.singletonList(IEntityItem.ItemType.PARAMETER);
042  }
043
044  @Override
045  public String getReferenceText(@NonNull InsertAnchorNode insert) {
046    return insert.getIdReference().toString();
047  }
048
049  @Override
050  public void setReferenceText(@NonNull InsertAnchorNode insert, @NonNull String newReference) {
051    insert.setIdReference(ObjectUtils.notNull(BasedSequence.of(newReference)));
052  }
053
054  @Override
055  protected boolean handleIndexMiss(
056      @NonNull IModelNodeItem<?, ?> contextItem,
057      @NonNull InsertAnchorNode insert,
058      @NonNull List<IEntityItem.ItemType> itemTypes,
059      @NonNull String identifier,
060      @NonNull ReferenceCountingVisitor.Context visitorContext) {
061    if (LOGGER.isErrorEnabled()) {
062      LOGGER.atError().log(
063          "The '{}' insert at '{}' should reference a '{}' identified by '{}'."
064              + " The index did not contain the identifier.",
065          insert.getType().toString(),
066          contextItem.toPath(IPathFormatter.METAPATH_PATH_FORMATER),
067          itemTypes.stream()
068              .map(type -> type.name().toLowerCase(Locale.ROOT))
069              .collect(CustomCollectors.joiningWithOxfordComma("or")),
070          identifier);
071    }
072    return true;
073  }
074
075}