001package gov.nist.secauto.oscal.lib.model; 002 003import gov.nist.secauto.metaschema.core.datatype.adapter.UuidAdapter; 004import gov.nist.secauto.metaschema.core.model.IBoundObject; 005import gov.nist.secauto.metaschema.core.model.IMetaschemaData; 006import gov.nist.secauto.metaschema.core.model.JsonGroupAsBehavior; 007import gov.nist.secauto.metaschema.core.util.ObjectUtils; 008import gov.nist.secauto.metaschema.databind.model.annotations.BoundAssembly; 009import gov.nist.secauto.metaschema.databind.model.annotations.BoundField; 010import gov.nist.secauto.metaschema.databind.model.annotations.BoundFlag; 011import gov.nist.secauto.metaschema.databind.model.annotations.GroupAs; 012import gov.nist.secauto.metaschema.databind.model.annotations.MetaschemaAssembly; 013import java.lang.Override; 014import java.lang.String; 015import java.util.LinkedList; 016import java.util.List; 017import java.util.UUID; 018import org.apache.commons.lang3.builder.ReflectionToStringBuilder; 019import org.apache.commons.lang3.builder.ToStringStyle; 020 021/** 022 * A plan of action and milestones which identifies initial and residual risks, deviations, and disposition, such as those required by FedRAMP. 023 */ 024@MetaschemaAssembly( 025 formalName = "Plan of Action and Milestones (POA&M)", 026 description = "A plan of action and milestones which identifies initial and residual risks, deviations, and disposition, such as those required by FedRAMP.", 027 name = "plan-of-action-and-milestones", 028 moduleClass = OscalPoamModule.class, 029 rootName = "plan-of-action-and-milestones", 030 remarks = "Either an OSCAL-based SSP must be imported, or a unique system-id must be specified. Both may be present." 031) 032public class PlanOfActionAndMilestones extends AbstractOscalInstance implements IBoundObject { 033 private final IMetaschemaData __metaschemaData; 034 035 /** 036 * "A <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#machine-oriented\">machine-oriented</a>, <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#globally-unique\">globally unique</a> identifier with <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#instance\">instance</a>scope that can be used to reference this POA&M instance in <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#poam-identifiers\">this OSCAL instance</a>. This UUID should be assigned <a href=\"https://pages.nist.gov/OSCAL/concepts/identifier-use/#consistency\">per-subject</a>, which means it should be consistently used to identify the same subject across revisions of the document." 037 */ 038 @BoundFlag( 039 formalName = "POA&M Universally Unique Identifier", 040 description = "A [machine-oriented](https://pages.nist.gov/OSCAL/concepts/identifier-use/#machine-oriented), [globally unique](https://pages.nist.gov/OSCAL/concepts/identifier-use/#globally-unique) identifier with [instance](https://pages.nist.gov/OSCAL/concepts/identifier-use/#instance)scope that can be used to reference this POA\\&M instance in [this OSCAL instance](https://pages.nist.gov/OSCAL/concepts/identifier-use/#poam-identifiers). This UUID should be assigned [per-subject](https://pages.nist.gov/OSCAL/concepts/identifier-use/#consistency), which means it should be consistently used to identify the same subject across revisions of the document.", 041 name = "uuid", 042 required = true, 043 typeAdapter = UuidAdapter.class 044 ) 045 private UUID _uuid; 046 047 @BoundAssembly( 048 formalName = "Document Metadata", 049 description = "Provides information about the containing document, and defines concepts that are shared across the document.", 050 useName = "metadata", 051 minOccurs = 1 052 ) 053 private Metadata _metadata; 054 055 @BoundAssembly( 056 formalName = "Import System Security Plan", 057 description = "Used by the assessment plan and POA\\&M to import information about the system.", 058 useName = "import-ssp", 059 remarks = "Used by the POA\\&M to import information about the system." 060 ) 061 private ImportSsp _importSsp; 062 063 @BoundField( 064 formalName = "System Identification", 065 description = "A [human-oriented](https://pages.nist.gov/OSCAL/concepts/identifier-use/#human-oriented), [globally unique](https://pages.nist.gov/OSCAL/concepts/identifier-use/#globally-unique) identifier with [cross-instance](https://pages.nist.gov/OSCAL/concepts/identifier-use/#cross-instance) scope that can be used to reference this system identification property elsewhere in [this or other OSCAL instances](https://pages.nist.gov/OSCAL/concepts/identifier-use/#scope). When referencing an externally defined `system identification`, the `system identification` must be used in the context of the external / imported OSCAL instance (e.g., uri-reference). This string should be assigned [per-subject](https://pages.nist.gov/OSCAL/concepts/identifier-use/#consistency), which means it should be consistently used to identify the same system across revisions of the document.", 066 useName = "system-id" 067 ) 068 private SystemId _systemId; 069 070 @BoundAssembly( 071 formalName = "Local Definitions", 072 description = "Allows components, and inventory-items to be defined within the POA\\&M for circumstances where no OSCAL-based SSP exists, or is not delivered with the POA\\&M.", 073 useName = "local-definitions" 074 ) 075 private LocalDefinitions _localDefinitions; 076 077 @BoundAssembly( 078 formalName = "Observation", 079 description = "Describes an individual observation.", 080 useName = "observation", 081 maxOccurs = -1, 082 groupAs = @GroupAs(name = "observations", inJson = JsonGroupAsBehavior.LIST) 083 ) 084 private List<Observation> _observations; 085 086 @BoundAssembly( 087 formalName = "Identified Risk", 088 description = "An identified risk.", 089 useName = "risk", 090 maxOccurs = -1, 091 groupAs = @GroupAs(name = "risks", inJson = JsonGroupAsBehavior.LIST) 092 ) 093 private List<Risk> _risks; 094 095 @BoundAssembly( 096 formalName = "Finding", 097 description = "Describes an individual finding.", 098 useName = "finding", 099 maxOccurs = -1, 100 groupAs = @GroupAs(name = "findings", inJson = JsonGroupAsBehavior.LIST) 101 ) 102 private List<Finding> _findings; 103 104 @BoundAssembly( 105 formalName = "POA&M Item", 106 description = "Describes an individual POA\\&M item.", 107 useName = "poam-item", 108 minOccurs = 1, 109 maxOccurs = -1, 110 groupAs = @GroupAs(name = "poam-items", inJson = JsonGroupAsBehavior.LIST) 111 ) 112 private List<PoamItem> _poamItems; 113 114 @BoundAssembly( 115 formalName = "Back matter", 116 description = "A collection of resources that may be referenced from within the OSCAL document instance.", 117 useName = "back-matter" 118 ) 119 private BackMatter _backMatter; 120 121 public PlanOfActionAndMilestones() { 122 this(null); 123 } 124 125 public PlanOfActionAndMilestones(IMetaschemaData data) { 126 this.__metaschemaData = data; 127 } 128 129 @Override 130 public IMetaschemaData getMetaschemaData() { 131 return __metaschemaData; 132 } 133 134 public UUID getUuid() { 135 return _uuid; 136 } 137 138 public void setUuid(UUID value) { 139 _uuid = value; 140 } 141 142 public Metadata getMetadata() { 143 return _metadata; 144 } 145 146 public void setMetadata(Metadata value) { 147 _metadata = value; 148 } 149 150 public ImportSsp getImportSsp() { 151 return _importSsp; 152 } 153 154 public void setImportSsp(ImportSsp value) { 155 _importSsp = value; 156 } 157 158 public SystemId getSystemId() { 159 return _systemId; 160 } 161 162 public void setSystemId(SystemId value) { 163 _systemId = value; 164 } 165 166 public LocalDefinitions getLocalDefinitions() { 167 return _localDefinitions; 168 } 169 170 public void setLocalDefinitions(LocalDefinitions value) { 171 _localDefinitions = value; 172 } 173 174 public List<Observation> getObservations() { 175 return _observations; 176 } 177 178 public void setObservations(List<Observation> value) { 179 _observations = value; 180 } 181 182 /** 183 * Add a new {@link Observation} item to the underlying collection. 184 * @param item the item to add 185 * @return {@code true} 186 */ 187 public boolean addObservation(Observation item) { 188 Observation value = ObjectUtils.requireNonNull(item,"item cannot be null"); 189 if (_observations == null) { 190 _observations = new LinkedList<>(); 191 } 192 return _observations.add(value); 193 } 194 195 /** 196 * Remove the first matching {@link Observation} item from the underlying collection. 197 * @param item the item to remove 198 * @return {@code true} if the item was removed or {@code false} otherwise 199 */ 200 public boolean removeObservation(Observation item) { 201 Observation value = ObjectUtils.requireNonNull(item,"item cannot be null"); 202 return _observations != null && _observations.remove(value); 203 } 204 205 public List<Risk> getRisks() { 206 return _risks; 207 } 208 209 public void setRisks(List<Risk> value) { 210 _risks = value; 211 } 212 213 /** 214 * Add a new {@link Risk} item to the underlying collection. 215 * @param item the item to add 216 * @return {@code true} 217 */ 218 public boolean addRisk(Risk item) { 219 Risk value = ObjectUtils.requireNonNull(item,"item cannot be null"); 220 if (_risks == null) { 221 _risks = new LinkedList<>(); 222 } 223 return _risks.add(value); 224 } 225 226 /** 227 * Remove the first matching {@link Risk} item from the underlying collection. 228 * @param item the item to remove 229 * @return {@code true} if the item was removed or {@code false} otherwise 230 */ 231 public boolean removeRisk(Risk item) { 232 Risk value = ObjectUtils.requireNonNull(item,"item cannot be null"); 233 return _risks != null && _risks.remove(value); 234 } 235 236 public List<Finding> getFindings() { 237 return _findings; 238 } 239 240 public void setFindings(List<Finding> value) { 241 _findings = value; 242 } 243 244 /** 245 * Add a new {@link Finding} item to the underlying collection. 246 * @param item the item to add 247 * @return {@code true} 248 */ 249 public boolean addFinding(Finding item) { 250 Finding value = ObjectUtils.requireNonNull(item,"item cannot be null"); 251 if (_findings == null) { 252 _findings = new LinkedList<>(); 253 } 254 return _findings.add(value); 255 } 256 257 /** 258 * Remove the first matching {@link Finding} item from the underlying collection. 259 * @param item the item to remove 260 * @return {@code true} if the item was removed or {@code false} otherwise 261 */ 262 public boolean removeFinding(Finding item) { 263 Finding value = ObjectUtils.requireNonNull(item,"item cannot be null"); 264 return _findings != null && _findings.remove(value); 265 } 266 267 public List<PoamItem> getPoamItems() { 268 return _poamItems; 269 } 270 271 public void setPoamItems(List<PoamItem> value) { 272 _poamItems = value; 273 } 274 275 /** 276 * Add a new {@link PoamItem} item to the underlying collection. 277 * @param item the item to add 278 * @return {@code true} 279 */ 280 public boolean addPoamItem(PoamItem item) { 281 PoamItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 282 if (_poamItems == null) { 283 _poamItems = new LinkedList<>(); 284 } 285 return _poamItems.add(value); 286 } 287 288 /** 289 * Remove the first matching {@link PoamItem} item from the underlying collection. 290 * @param item the item to remove 291 * @return {@code true} if the item was removed or {@code false} otherwise 292 */ 293 public boolean removePoamItem(PoamItem item) { 294 PoamItem value = ObjectUtils.requireNonNull(item,"item cannot be null"); 295 return _poamItems != null && _poamItems.remove(value); 296 } 297 298 public BackMatter getBackMatter() { 299 return _backMatter; 300 } 301 302 public void setBackMatter(BackMatter value) { 303 _backMatter = value; 304 } 305 306 @Override 307 public String toString() { 308 return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).toString(); 309 } 310}