001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package gov.nist.secauto.oscal.lib.model.control; 007 008import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; 009import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; 010import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension; 011import gov.nist.secauto.metaschema.core.datatype.markup.flexmark.InsertAnchorExtension.InsertAnchorNode; 012import gov.nist.secauto.metaschema.core.util.CollectionUtil; 013import gov.nist.secauto.metaschema.core.util.ObjectUtils; 014import gov.nist.secauto.oscal.lib.model.ControlPart; 015import gov.nist.secauto.oscal.lib.model.Link; 016import gov.nist.secauto.oscal.lib.model.Property; 017 018import java.net.URI; 019import java.util.LinkedList; 020import java.util.List; 021import java.util.Objects; 022import java.util.function.Predicate; 023import java.util.stream.Stream; 024 025import edu.umd.cs.findbugs.annotations.NonNull; 026 027public abstract class AbstractPart implements IPart { 028 029 @Override 030 @NonNull 031 public Stream<InsertAnchorExtension.InsertAnchorNode> getInserts(@NonNull Predicate<InsertAnchorNode> filter) { 032 MarkupMultiline prose = getProse(); 033 034 @NonNull 035 Stream<InsertAnchorExtension.InsertAnchorNode> retval; 036 if (prose == null) { 037 retval = ObjectUtils.notNull(Stream.empty()); 038 } else { 039 List<InsertAnchorExtension.InsertAnchorNode> result = prose.getInserts(filter); 040 retval = ObjectUtils.notNull(result.stream()); 041 } 042 return retval; 043 } 044 045 public Stream<IPart> getPartsRecursively() { 046 return Stream.concat( 047 Stream.of(this), 048 CollectionUtil.listOrEmpty(getParts()).stream() 049 .flatMap(AbstractPart::getPartsRecursively)); 050 } 051 052 @NonNull 053 public static Builder builder(@NonNull String name) { 054 return new Builder(name); 055 } 056 057 public static class Builder { 058 private String id; 059 @NonNull 060 private final String name; 061 private URI namespace; 062 private String clazz; 063 private MarkupMultiline prose; 064 private MarkupLine title; 065 private final List<Property> props = new LinkedList<>(); 066 private final List<Link> links = new LinkedList<>(); 067 private final List<ControlPart> parts = new LinkedList<>(); 068 069 public Builder(@NonNull String name) { 070 this.name = Objects.requireNonNull(name); 071 } 072 073 @SuppressWarnings("PMD.ShortMethodName") 074 @NonNull 075 public Builder id(@NonNull String value) { 076 this.id = Objects.requireNonNull(value); 077 return this; 078 } 079 080 @NonNull 081 public Builder namespace(@NonNull URI value) { 082 this.namespace = Objects.requireNonNull(value); 083 return this; 084 } 085 086 @NonNull 087 public Builder clazz(@NonNull String value) { 088 this.clazz = Objects.requireNonNull(value); 089 return this; 090 } 091 092 @NonNull 093 public Builder title(@NonNull String markdown) { 094 return title(MarkupLine.fromMarkdown(Objects.requireNonNull(markdown))); 095 } 096 097 @NonNull 098 public Builder title(@NonNull MarkupLine value) { 099 this.title = Objects.requireNonNull(value); 100 return this; 101 } 102 103 @NonNull 104 public Builder prose(@NonNull String markdown) { 105 return prose(MarkupMultiline.fromMarkdown(Objects.requireNonNull(markdown))); 106 } 107 108 @NonNull 109 public Builder prose(@NonNull MarkupMultiline value) { 110 this.prose = Objects.requireNonNull(value); 111 return this; 112 } 113 114 @NonNull 115 public Builder prop(@NonNull Property value) { 116 this.props.add(Objects.requireNonNull(value)); 117 return this; 118 } 119 120 @NonNull 121 public Builder link(@NonNull Link value) { 122 this.links.add(Objects.requireNonNull(value)); 123 return this; 124 } 125 126 @NonNull 127 public Builder part(@NonNull ControlPart value) { 128 this.parts.add(Objects.requireNonNull(value)); 129 return this; 130 } 131 132 @NonNull 133 public ControlPart build() { 134 ControlPart retval = new ControlPart(); 135 136 retval.setName(name); 137 138 if (id != null) { 139 retval.setId(id); 140 } 141 if (namespace != null) { 142 retval.setNs(namespace); 143 } 144 if (clazz != null) { 145 retval.setClazz(clazz); 146 } 147 if (prose != null) { 148 retval.setProse(prose); 149 } 150 if (title != null) { 151 retval.setTitle(title); 152 } 153 if (!props.isEmpty()) { 154 retval.setProps(props); 155 } 156 if (!links.isEmpty()) { 157 retval.setLinks(links); 158 } 159 if (!parts.isEmpty()) { 160 retval.setParts(parts); 161 } 162 return retval; 163 } 164 } 165}