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