001/* 002 * Portions of this software was developed by employees of the National Institute 003 * of Standards and Technology (NIST), an agency of the Federal Government and is 004 * being made available as a public service. Pursuant to title 17 United States 005 * Code Section 105, works of NIST employees are not subject to copyright 006 * protection in the United States. This software may be subject to foreign 007 * copyright. Permission in the United States and in foreign countries, to the 008 * extent that NIST may hold copyright, to use, copy, modify, create derivative 009 * works, and distribute this software and its documentation without fee is hereby 010 * granted on a non-exclusive basis, provided that this notice and disclaimer 011 * of warranty appears in all copies. 012 * 013 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER 014 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY 015 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF 016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM 017 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE 018 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE. IN NO EVENT 019 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT, 020 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM, 021 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY, 022 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR 023 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT 024 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER. 025 */ 026 027package gov.nist.secauto.metaschema.core.model; 028 029import gov.nist.secauto.metaschema.core.datatype.markup.MarkupLine; 030import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline; 031import gov.nist.secauto.metaschema.core.util.ObjectUtils; 032 033import java.net.URI; 034import java.util.Collection; 035import java.util.List; 036import java.util.function.Predicate; 037import java.util.stream.Collectors; 038import java.util.stream.Stream; 039 040import javax.xml.namespace.QName; 041 042import edu.umd.cs.findbugs.annotations.NonNull; 043import edu.umd.cs.findbugs.annotations.Nullable; 044 045/** 046 * The API for accessing information about a given Metaschema. 047 * <p> 048 * A Metaschem module may import another Metaschema module. This import graph 049 * can be accessed using {@link #getImportedModules()}. 050 * <p> 051 * Global scoped Metaschema definitions can be accessed using 052 * {@link #getScopedAssemblyDefinitionByName(String)}, 053 * {@link #getScopedFieldDefinitionByName(String)}, and 054 * {@link #getScopedFlagDefinitionByName(String)}. These methods take into 055 * consideration the import order to provide the global definitions that are in 056 * scope within the given Metschema module. 057 * <p> 058 * Global scoped definitions exported by this Metaschema module, available for 059 * use by importing Metaschema modules, can be accessed using 060 * {@link #getExportedAssemblyDefinitions()}, 061 * {@link #getExportedFieldDefinitions()}, and 062 * {@link #getExportedFlagDefinitions()}. 063 * <p> 064 * Global scoped definitions defined directly within the given Metaschema module 065 * can be accessed using {@link #getAssemblyDefinitions()}, 066 * {@link #getFieldDefinitions()}, and {@link #getFlagDefinitions()}, along with 067 * similarly named access methods. 068 */ 069// REFACTOR: rename to IModule 070public interface IModule { 071 String METASCHEMA_XML_NS = "http://csrc.nist.gov/ns/oscal/metaschema/1.0"; 072 073 /** 074 * Get a filter that will match all definitions that are not locally defined. 075 * 076 * @param <DEF> 077 * the type of definition 078 * @return a predicate implementing the filter 079 */ 080 static <DEF extends IDefinition> Predicate<DEF> allNonLocalDefinitions() { 081 return definition -> { 082 return ModuleScopeEnum.INHERITED.equals(definition.getModuleScope()) 083 || ModelType.ASSEMBLY.equals(definition.getModelType()) && ((IAssemblyDefinition) definition).isRoot(); 084 }; 085 } 086 087 /** 088 * Get a filter that will match all definitions that are root assemblies. 089 * 090 * @param <DEF> 091 * the type of definition 092 * @return a predicate implementing the filter 093 */ 094 static <DEF extends IDefinition> Predicate<DEF> allRootAssemblyDefinitions() { 095 return definition -> { 096 return ModelType.ASSEMBLY.equals(definition.getModelType()) && ((IAssemblyDefinition) definition).isRoot(); 097 }; 098 } 099 100 /** 101 * Retrieves the location where the Metaschema module was loaded from. 102 * 103 * @return the location, or {@code null} if this information is not available 104 */ 105 URI getLocation(); 106 107 /** 108 * Get the long name for the Metaschema module. 109 * 110 * @return the name 111 */ 112 @NonNull 113 MarkupLine getName(); 114 115 /** 116 * Get the revision of the Metaschema module. 117 * 118 * @return the revision 119 */ 120 @NonNull 121 String getVersion(); 122 123 /** 124 * Retrieve the remarks associated with this Metaschema module, if any. 125 * 126 * @return the remarks or {@code null} if no remarks are defined 127 */ 128 @Nullable 129 MarkupMultiline getRemarks(); 130 131 /** 132 * Retrieves the unique short name for the Metaschema module, which provides a 133 * textual identifier for the Metaschema module. 134 * 135 * @return the short name 136 */ 137 @NonNull 138 String getShortName(); 139 140 /** 141 * Retrieves the XML namespace associated with the Metaschema module. 142 * 143 * @return a namespace 144 */ 145 @NonNull 146 URI getXmlNamespace(); 147 148 /** 149 * Retrieve the JSON schema base URI associated with the Metaschema module. 150 * 151 * @return the base URI 152 */ 153 @NonNull 154 URI getJsonBaseUri(); 155 156 /** 157 * Get the qualified name associated with the Metaschema module. 158 * 159 * @return the qualified name 160 */ 161 default QName getQName() { 162 return new QName(getXmlNamespace().toString(), getShortName()); 163 } 164 165 /** 166 * Retrieves all Metaschema modules imported by this Metaschema module. 167 * 168 * @return a list of imported Metaschema modules 169 */ 170 @NonNull 171 List<? extends IModule> getImportedModules(); 172 173 /** 174 * Retrieve the imported Metaschema module with the specified name, if it 175 * exists. 176 * 177 * @param name 178 * the short name of the Metschema module to retrieve 179 * @return the imported Metaschema module or {@code null} if it doesn't exist 180 */ 181 @Nullable 182 IModule getImportedModuleByShortName(String name); 183 184 /** 185 * Retrieves the top-level assembly definitions in this Metaschema module. 186 * 187 * @return the collection of assembly definitions 188 */ 189 @NonNull 190 Collection<? extends IAssemblyDefinition> getAssemblyDefinitions(); 191 192 /** 193 * Retrieves the top-level assembly definition in this Metaschema module with 194 * the matching name, if it exists. 195 * 196 * @param name 197 * the definition name 198 * 199 * @return the matching assembly definition, or {@code null} if none match 200 */ 201 @Nullable 202 IAssemblyDefinition getAssemblyDefinitionByName(@NonNull String name); 203 204 /** 205 * Retrieves the top-level field definitions in this Metaschema module. 206 * 207 * @return the collection of field definitions 208 */ 209 @NonNull 210 Collection<? extends IFieldDefinition> getFieldDefinitions(); 211 212 /** 213 * Retrieves the top-level field definition in this Metaschema module with the 214 * matching name, if it exists. 215 * 216 * @param name 217 * the definition name 218 * 219 * @return the matching field definition, or {@code null} if none match 220 */ 221 @Nullable 222 IFieldDefinition getFieldDefinitionByName(@NonNull String name); 223 224 /** 225 * Retrieves the top-level assembly and field definitions in this Metaschema 226 * module. 227 * 228 * @return a listing of assembly and field definitions 229 */ 230 @NonNull 231 default List<? extends IFlagContainer> getAssemblyAndFieldDefinitions() { 232 return ObjectUtils.notNull( 233 Stream.concat(getAssemblyDefinitions().stream(), getFieldDefinitions().stream()) 234 .collect(Collectors.toList())); 235 } 236 237 /** 238 * Retrieves the top-level flag definitions in this Metaschema module. 239 * 240 * @return the collection of flag definitions 241 */ 242 @NonNull 243 Collection<? extends IFlagDefinition> getFlagDefinitions(); 244 245 /** 246 * Retrieves the top-level flag definition in this Metaschema module with the 247 * matching name, if it exists. 248 * 249 * @param name 250 * the definition name 251 * 252 * @return the matching flag definition, or {@code null} if none match 253 */ 254 @Nullable 255 IFlagDefinition getFlagDefinitionByName(@NonNull String name); 256 257 // /** 258 // * Retrieves the information elements matching the path. 259 // * 260 // * @param path 261 // * a MetaPath expression 262 // * @return the matching information elements or an empty collection 263 // */ 264 // @NonNull 265 // Collection<@NonNull ? extends IModelElement> 266 // getInfoElementsByMetapath(@NonNull String path); 267 268 /** 269 * Retrieves the assembly definition with a matching name from either: 1) the 270 * top-level assembly definitions from this Metaschema module, or 2) global 271 * assembly definitions from each imported Metaschema module in reverse order of 272 * import. 273 * 274 * @param name 275 * the name of the assembly to find 276 * @return the assembly definition 277 */ 278 @Nullable 279 default IAssemblyDefinition getScopedAssemblyDefinitionByName(@NonNull String name) { 280 // first try local/global top-level definitions from current metaschema module 281 IAssemblyDefinition retval = getAssemblyDefinitionByName(name); 282 if (retval == null) { 283 // try global definitions from imported Metaschema modules 284 retval = getExportedAssemblyDefinitionByName(name); 285 } 286 return retval; 287 } 288 289 /** 290 * Retrieves the field definition with a matching name from either: 1) the 291 * top-level field definitions from this Metaschema module, or 2) global field 292 * definitions from each imported Metaschema module in reverse order of import. 293 * 294 * @param name 295 * the name of the field definition to find 296 * @return the field definition 297 */ 298 @Nullable 299 default IFieldDefinition getScopedFieldDefinitionByName(@NonNull String name) { 300 // first try local/global top-level definitions from current metaschema module 301 IFieldDefinition retval = getFieldDefinitionByName(name); 302 if (retval == null) { 303 // try global definitions from imported metaschema modules 304 retval = getExportedFieldDefinitionByName(name); 305 } 306 return retval; 307 } 308 309 /** 310 * Retrieves the flag definition with a matching name from either: 1) the 311 * top-level flag definitions from this Metaschema module, or 2) global flag 312 * definitions from each imported Metaschema module in reverse order of import. 313 * 314 * @param name 315 * the name of the flag definition to find 316 * @return the flag definition 317 */ 318 @Nullable 319 default IFlagDefinition getScopedFlagDefinitionByName(@NonNull String name) { 320 // first try local/global top-level definitions from current metaschema module 321 IFlagDefinition retval = getFlagDefinitionByName(name); 322 if (retval == null) { 323 // try global definitions from imported metaschema modules 324 retval = getExportedFlagDefinitionByName(name); 325 } 326 return retval; 327 } 328 329 /** 330 * Retrieves the top-level assembly definitions that are marked as roots from 331 * the current Metaschema module and any imported Metaschema modules. 332 * 333 * @return a listing of assembly definitions marked as root 334 */ 335 @NonNull 336 default Collection<? extends IAssemblyDefinition> getExportedRootAssemblyDefinitions() { 337 return ObjectUtils.notNull(getExportedAssemblyDefinitions().stream() 338 .filter(allRootAssemblyDefinitions()) 339 .collect(Collectors.toList())); 340 } 341 342 /** 343 * Retrieves the top-level assembly definitions that are marked as roots from 344 * the current Metaschema module. 345 * 346 * @return a listing of assembly definitions marked as root 347 */ 348 @NonNull 349 default Collection<? extends IAssemblyDefinition> getRootAssemblyDefinitions() { 350 return ObjectUtils.notNull(getAssemblyDefinitions().stream() 351 .filter(allRootAssemblyDefinitions()) 352 .collect(Collectors.toList())); 353 } 354 355 /** 356 * Retrieve the top-level flag definitions that are marked global in this 357 * Metaschema module or in any imported Metaschema modules. The resulting 358 * collection is built by adding global definitions from each imported 359 * Metaschema module in order of import, then adding global definitions from the 360 * current Metaschema module. Such a map is built in this way for each imported 361 * Metaschema module in the chain. Values for clashing keys will be replaced in 362 * this order, giving preference to the "closest" definition. 363 * 364 * @return the collection of exported flag definitions 365 */ 366 @NonNull 367 Collection<? extends IFlagDefinition> getExportedFlagDefinitions(); 368 369 /** 370 * Retrieves the exported named flag definition, if it exists. 371 * <p> 372 * For information about how flag definitions are exported see 373 * {@link #getExportedFlagDefinitions()}. 374 * 375 * @param name 376 * the definition name 377 * @return the flag definition, or {@code null} if it doesn't exist. 378 */ 379 @Nullable 380 IFlagDefinition getExportedFlagDefinitionByName(String name); 381 382 /** 383 * Retrieve the top-level field definitions that are marked global in this 384 * Metaschema module or in any imported Metaschema module. The resulting 385 * collection is built by adding global definitions from each imported 386 * Metaschema module in order of import, then adding global definitions from the 387 * current Metaschema module. Such a map is built in this way for each imported 388 * Metaschema module in the chain. Values for clashing keys will be replaced in 389 * this order, giving preference to the "closest" definition 390 * 391 * @return the collection of exported field definitions 392 */ 393 @NonNull 394 Collection<? extends IFieldDefinition> getExportedFieldDefinitions(); 395 396 /** 397 * Retrieves the exported named field definition, if it exists. 398 * <p> 399 * For information about how field definitions are exported see 400 * {@link #getExportedFieldDefinitions()}. 401 * 402 * @param name 403 * the definition name 404 * @return the field definition, or {@code null} if it doesn't exist. 405 */ 406 @Nullable 407 IFieldDefinition getExportedFieldDefinitionByName(String name); 408 409 /** 410 * Retrieve the top-level assembly definitions that are marked global in this 411 * Metaschema module or in any imported Metaschema module. The resulting 412 * collection is built by adding global definitions from each imported 413 * Metaschema module in order of import, then adding global definitions from the 414 * current Metaschema module. This collection is built in this way for each 415 * imported Metaschema module in the chain. Items with duplicate names will be 416 * replaced in this order, giving preference to the "closest" definition 417 * 418 * @return the collection of exported assembly definitions 419 */ 420 @NonNull 421 Collection<? extends IAssemblyDefinition> getExportedAssemblyDefinitions(); 422 423 /** 424 * Retrieves the exported named assembly definition, if it exists. 425 * <p> 426 * For information about how assembly definitions are exported see 427 * {@link #getExportedFieldDefinitions()}. 428 * 429 * @param name 430 * the definition name 431 * @return the assembly definition, or {@code null} if it doesn't exist. 432 */ 433 @Nullable 434 IAssemblyDefinition getExportedAssemblyDefinitionByName(String name); 435}