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 gov.nist.secauto.metaschema.core.metapath.format.IPathFormatter; 009import gov.nist.secauto.metaschema.core.metapath.item.node.IModelNodeItem; 010import gov.nist.secauto.metaschema.core.util.CustomCollectors; 011import gov.nist.secauto.metaschema.core.util.ObjectUtils; 012import gov.nist.secauto.oscal.lib.model.Property; 013import gov.nist.secauto.oscal.lib.profile.resolver.support.IEntityItem; 014 015import org.apache.logging.log4j.LogManager; 016import org.apache.logging.log4j.Logger; 017 018import java.net.URI; 019import java.util.List; 020import java.util.Locale; 021 022import edu.umd.cs.findbugs.annotations.NonNull; 023 024public class PropertyReferencePolicy 025 extends AbstractMultiItemTypeReferencePolicy<Property> { 026 private static final Logger LOGGER = LogManager.getLogger(PropertyReferencePolicy.class); 027 028 @NonNull 029 public static PropertyReferencePolicy create(@NonNull IIdentifierParser identifierParser, 030 @NonNull IEntityItem.ItemType itemType) { 031 return create(identifierParser, ObjectUtils.notNull(List.of(itemType))); 032 } 033 034 @NonNull 035 public static PropertyReferencePolicy create(@NonNull IIdentifierParser identifierParser, 036 @NonNull List<IEntityItem.ItemType> itemTypes) { 037 return new PropertyReferencePolicy(identifierParser, itemTypes); 038 } 039 040 public PropertyReferencePolicy( 041 @NonNull IIdentifierParser identifierParser, 042 @NonNull List<IEntityItem.ItemType> itemTypes) { 043 super(identifierParser, itemTypes); 044 } 045 046 @Override 047 public String getReferenceText(@NonNull Property property) { 048 return property.getValue(); 049 } 050 051 @Override 052 public void setReferenceText(@NonNull Property property, @NonNull String newValue) { 053 property.setValue(newValue); 054 } 055 056 @Override 057 protected void handleUnselected( 058 @NonNull IModelNodeItem<?, ?> contextItem, 059 @NonNull Property property, 060 @NonNull IEntityItem item, 061 @NonNull ReferenceCountingVisitor.Context visitorContext) { 062 URI linkHref = URI.create(property.getValue()); 063 URI sourceUri = item.getSource(); 064 065 URI resolved = sourceUri.resolve(linkHref); 066 if (LOGGER.isDebugEnabled()) { 067 LOGGER.atTrace().log("At path '{}', remapping orphaned URI '{}' to '{}'", 068 contextItem.toPath(IPathFormatter.METAPATH_PATH_FORMATER), 069 linkHref.toString(), 070 resolved.toString()); 071 } 072 property.setValue(resolved.toString()); 073 } 074 075 @Override 076 protected boolean handleIndexMiss( 077 @NonNull IModelNodeItem<?, ?> contextItem, 078 @NonNull Property property, 079 @NonNull List<IEntityItem.ItemType> itemTypes, 080 @NonNull String identifier, 081 @NonNull ReferenceCountingVisitor.Context visitorContext) { 082 if (LOGGER.isWarnEnabled()) { 083 LOGGER.atWarn().log( 084 "The property '{}' at '{}' should reference a {} identified by '{}'," 085 + " but the identifier was not found in the index.", 086 property.getQName(), 087 contextItem.toPath(IPathFormatter.METAPATH_PATH_FORMATER), 088 itemTypes.stream() 089 .map(en -> en.name().toLowerCase(Locale.ROOT)) 090 .collect(CustomCollectors.joiningWithOxfordComma("or")), 091 identifier); 092 } 093 return true; 094 } 095}