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