001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package gov.nist.secauto.oscal.lib.model.metadata; 007 008import gov.nist.secauto.metaschema.core.qname.IEnhancedQName; 009import gov.nist.secauto.metaschema.core.util.CollectionUtil; 010import gov.nist.secauto.metaschema.core.util.ObjectUtils; 011import gov.nist.secauto.oscal.lib.model.Property; 012 013import java.net.URI; 014import java.util.LinkedList; 015import java.util.List; 016import java.util.Objects; 017import java.util.Optional; 018import java.util.UUID; 019import java.util.stream.Collectors; 020import java.util.stream.Stream; 021 022import edu.umd.cs.findbugs.annotations.NonNull; 023 024public abstract class AbstractProperty implements IProperty { 025 026 @NonNull 027 public static IEnhancedQName qname(@NonNull URI namespace, @NonNull String name) { 028 return IEnhancedQName.of(ObjectUtils.notNull(namespace.toASCIIString()), name); 029 } 030 031 @NonNull 032 public static IEnhancedQName qname(@NonNull String name) { 033 return IEnhancedQName.of(ObjectUtils.notNull(IProperty.normalizeNamespace(null).toASCIIString()), name); 034 } 035 036 @SuppressWarnings("null") 037 @NonNull 038 public static Optional<Property> find(List<Property> props, @NonNull IEnhancedQName qname) { 039 return CollectionUtil.listOrEmpty(props).stream().filter(prop -> qname.equals(prop.getQName())).findFirst(); 040 } 041 042 protected AbstractProperty() { 043 // only concrete classes should construct 044 } 045 046 public static List<Property> merge(@NonNull List<Property> original, @NonNull List<Property> additional) { 047 return Stream.concat(original.stream(), additional.stream()) 048 .collect(Collectors.toCollection(LinkedList::new)); 049 } 050 051 @Override 052 public boolean isNamespaceEqual(@NonNull URI namespace) { 053 return IProperty.normalizeNamespace(getNs()).equals(namespace); 054 } 055 056 @NonNull 057 public IEnhancedQName getQName() { 058 return qname( 059 IProperty.normalizeNamespace(getNs()), 060 ObjectUtils.requireNonNull(getName())); 061 } 062 063 @NonNull 064 public static Builder builder(@NonNull String name) { 065 return new Builder(name); 066 } 067 068 public static class Builder { 069 @NonNull 070 private final String name; 071 072 private UUID uuid; 073 private URI namespace; 074 private String value; 075 private String clazz; 076 077 public Builder(@NonNull String name) { 078 this.name = Objects.requireNonNull(name, "name"); 079 } 080 081 @NonNull 082 public Builder uuid(@NonNull UUID uuid) { 083 this.uuid = Objects.requireNonNull(uuid); 084 return this; 085 } 086 087 @SuppressWarnings("PMD.NullAssignment") // needed 088 @NonNull 089 public Builder namespace(@NonNull URI namespace) { 090 if (OSCAL_NAMESPACE.equals(namespace)) { 091 this.namespace = null; 092 } else { 093 this.namespace = Objects.requireNonNull(namespace); 094 } 095 return this; 096 } 097 098 @NonNull 099 public Builder value(@NonNull String value) { 100 this.value = Objects.requireNonNull(value); 101 return this; 102 } 103 104 @NonNull 105 public Builder clazz(@NonNull String clazz) { 106 this.clazz = Objects.requireNonNull(clazz); 107 return this; 108 } 109 110 @NonNull 111 public Property build() { 112 Property retval = new Property(); 113 retval.setName(name); 114 retval.setValue(Objects.requireNonNull(value, "value")); 115 if (uuid != null) { 116 retval.setUuid(uuid); 117 } 118 if (namespace != null) { 119 retval.setNs(namespace); 120 } 121 if (clazz != null) { 122 retval.setClazz(clazz); 123 } 124 125 return retval; 126 } 127 } 128}