In springdocs, can I define multiple OpenAPI definitions based on tags on the operations - springdoc

I need to define two different OpenApi definitions using springdocs for the same API within a single application: one for internal developers and one for external developers. The external definition would include some of the operations from the internal definition, but not all of them.
I have looked at using GroupedOpenApi to create the two definitions, but this requires that I move the endpoints that should be excluded from the external definition into a separate RestController and move to an excluded package, which would not be included in the definition for the external developers, but would still be included in the internal definition. I would prefer to structure my code based on the API definition and not based on the security access for my endpoints.
This seems like either SecurityScheme or tags could be used to define which operations are included in a given definition using something like GroupedOpenApi with the paths/packages to include. So for example, I could define the definition for my external API with something like the following:
GroupedOpenApi.builder()
.group("externalGroupName")
.securitySchemesToInclude("externalSchemeName") // this doesn't currently exist
.build();
And then any of the operations that are tagged with a SecurityRequirement with that SecurityScheme would get added to this external definition. So for example I could have the following two endpoints defined within the same RestController:
Would be included:
#SecurityRequirement(name = "externalSchemeName")
#GET
#Path("/pets")
public Response getResponse(){
return null;
}
}
Would not be included:
#SecurityRequirement(name = "internalSchemeName")
#GET
#Path("/pets/internal")
public Response getInternalResponse(){
return null;
}
}
With this approach, it would be nice to provide for include/excluded security schemes similar to paths/package inclusions/exclusions.
This seems like it would currently require a contribution to springdocs unless I am misunderstanding my options for how to create multiple definitions. Is there another way to achieve excluding an operation from only one of the definitions I define without completely hiding that operation from all definitions and without restructuring my packages?
Note that I also would prefer not to maintain a list of all the paths that should be excluded from the group in config if possible as this is error prone and doesn't allow for providing a shared config across multiple services. I would prefer an annotation-driven method similar to the way other swagger customization is done so that I define the config once and then update each resource as it is defined or modified based on an annotation to drive the swagger that is generated.

Using you example, you have other filters (based on paths) of GroupedOpenApi, that you haven't used:
GroupedOpenApi.builder()
.group("internalGroupName")
.pathsToMatch("/pets/internal")
.build();
GroupedOpenApi.builder()
.group("externalGroupName")
.pathsToMatch("/pets")
.packagesToExclude("/pets/internal")
.build();

Related

Accessing regmap RegFields

I am trying to find a clean way to access the regmap that is used with *RegisterNode for creating documentation and testing files. The TLRegisterNode has methods for generating the json through some Annotations. These are done in the regmap method by adding them to the ElaborationArtefacts object. Other protocols don't seem to have these annotations.
Is there anyway to iterate over the "regmap" Register Fields post elaboration or during?
I cannot just access the regmap as it's not really a val/var since it's a method. I can't quite figure out where this information is being stored. I don't really believe it's actually "storing" any information as much as it is simply creating the hardware to attach the specified logic to the RegisterNode based logic.
The JSON output is actually fine for me as I could just write a post processing script to convert JSON to my required formats, but I'm wondering if I can access this information OR if I could add a custom function call at the end. I cannot extend the case class *RegisterNode, but I'm not sure if it's possible to add custom functions to run at the end of the regmap method.
Here is something I threw together quickly:
//in *RegisterRouter.scala
def customregmap(customFunc: (RegField.Map*) => Unit, mapping: RegField.Map*) = {
regmap(mapping:_*)
customFunc(mapping:_*)
}
def regmap(mapping: RegField.Map*) = {
//normal stuff
}
A user could then create a custom function to run and pass it to the regmap or to the RegisterRouter
def myFunc(mapping: RegField.Map*): Unit = {
println("I'm doing my custom function for regmap!")
}
// ...
node.customregmap(myFunc,
0x0 -> coreControlRegFields,
0x4 -> fdControlRegFields,
0x8 -> fdControl2RegFields,
)
This is just a quick example I have. I believe what would be better, if something like this was possible, would be to have a Seq of functions that could be added to the RegisterNode that are ran at the end of the regmap method, similar to how TLRegisterNode currently works. So a user could add an arbitrary number and you still use the regmap call.
Background (not directly part of question):
I have a unified register script that I have built over the years in which I describe the registers for a particular IP. It works very similar to the RegField/node.regmap, except it obviously doesn't know about diplomacy and the like. It will generate the Verilog, but also a variety of files for DV (basic `defines for simple verilog simulations and more complex uvm_reg_block defines also with the ability to describe multiple of the IPs for a subsystem all the way up to an SoC level). It will also print out C Header files for SW and Sphinx reStructuredText for documentation.
Diplomacy actually solves one of the main issues I've been dealing with so I'm obviously trying to push most of my newer designs to Chisel/Diplo.
I ended up solving this by creating my own RegisterNode which is the same as the rocketchip RegisterNodes except that I use a different Elaboration Artifact to grab the info and store it for later.

How to include a remote vocabulary/namespace to OntModel using Jena?

I'm new to Semantic Web and Jena.
I want to generate an ontology from a OntModel in Jena and I need to use vocabulary and ontologies predefined to caracterize my classes and properties.
In Jena, there are default ontologies like RDF, FOAF...So we can specify class and add property to resource like:
ontClass.setSameAs(FOAF.Person);
ontClass.addProperty(FOAF.name, "name");
or
ontProperty.setRange(XSD.xstring);
But how can I refer my ontClass to another vocabulary/ontology that does not exist in Jena (GeoSparql, Geofla, vocabulary that I defined myself,etc.)? Knowing that I can have the URI for these vocabularies?
This question's already been raised in this topic: How to add vocabulary in Jena? which suggests using Jena Schemagen but I can't see how to do it.
Thank you a lot for helping!
I guess one of the option is to import (or read) theses vocabularies/ontologies so that you can use them using Jena Ontology API.
For example (if we assume that your ontModel is named m) you can read the OWL-Time ontology into your model like so :
m.read("http://www.w3.org/2006/time")
and then you can use the elements it defines using Jena's programmatic API :
OntClass instant = dataModel.getOntClass("http://www.w3.org/2006/time#Instant");
If you don't wan't to read the whole ontology within your model, you can also just "create" the necessary ressource / property using its URI :
Property inXSDDateTime = m.createDatatypeProperty(
"http://www.w3.org/2006/time#inXSDDateTime");
Resource resource = m.createResource("someURIForThisRessource");
Statement s = m.createStatement(
resource, inXSDDateTime, m.createTypedLiteral(someValue));
m.add(s);
It should write the result as expected (but, by doing this, you are not loading the axioms of the ontology you are referencing, so you won't be able to reason about it - but according to your comment, I'm thinking maybe that's what you want)

What is the difference between LSP and OCP?

I have been trying to break down the differences between the Open Closed Principal and Liskov's Substitution Principal. And the best and most common examples of either use the exact same problem. Finding the Area of a shape class.
They use slightly different means, but effectively solve the same problem with the same solution.
As these are both parts of SOLID, I'm really trying to find a reason to support why both are called out.
I'm looking for an explanation that doesn't work for both.
Thanks.
LSP:
Consumers target an abstraction (e.g. interface) and should not need to know which concrete implementation stands behind the interface. For example, a client (e.g. a DocumentProcessor class) holds a dependency on IDocumentStore. If in V1, you gave it a SqlSeverDocumentStore instance, and then in V2 you gave it a FileSystemDocumentStore, the client (DocumentProcessor) should work without modification. This can be achieved by making sure the contract of IDocumentStore is well defined and that DocumentProcessor, SqlSeverDocumentStore and FileSystemDocumentStore abide by this contract.
The contract means much more than an interface. Having two classes implement the same interface does not mean they abide by the same contract (although they should).
For example, does both implementations support saving documents which are smaller or equal to 20MB? Or does one of them support documents that are at most 10MB? If it is part of the contract that an implementation should support 20MB documents, then all implementations should support this.
OCP:
We should avoid modifying a unit of composition (e.g. a class or a function) after we release it. One way to achieve this is to make the units parameterized. For example, if you have a function (say, ProcessImages) that reads images from the file system, compresses them and then sends them to some web service, you can parameterize this function to accept other functions that are responsible for (1) reading images, (2) compressing them, (3) sending them.
E.g. (in C#):
public static void ProcessImages(
Func<Image[]> getImages,
Func<Image, CompressedImage> compressImage,
Action<CompressedImage> sendImage)
{
//... Orchestrate the operation here
}
And, in the Composition Root:
Action processImages = () => ProcessImages(ReadImages, CompressImage, SendImage);
Where ReadImages, CompressImage, SendImage are themselves functions.
This way, if you want to change how the images are compressed, you will not modify the ProcessImages function. Instead you will create a new compression function (say CompressImageInADifferentWay) and then compose the ProcessImages function in the Composition Root like this:
Action processImages =
() => ProcessImages(ReadImages, CompressImageInADifferentWay, SendImage);
If you apply the OCP in a perfect way, only the Composition Root itself will change.
LSP allows us to achieve OCP. For example, because CompressImage and CompressImageInADifferentWay abide by some contract that ProcessImages knows about, we can replace CompressImage with CompressImageInADifferentWay without modifying ProcessImages.

'import' a cujojs/wire context into another

I'm looking for a way to realize the following use-case:
I have many modules and each one of them has a wire spec that
exposes its components
To assemble an application, I select the modules and use their wire-spec
The wire-spec of the application is the merge of wire-specs of used
modules: (3.1) I start by 'requiring' the wire-spec of each module
as objects. (3.2) Then, I merge the objects. (3.3) And, finally, I
return the result as the object defining the wire-spec of the
application.
Here is a sample of an application context-spec:
define(["jquery", "module1-wire-spec", "module2-wire-spec"], function(jquery, module1WireSpec, module2WireSpec) {
return jquery.extend(true, module1WireSpec, module2WireSpec);
});
I have read several times wire documentation hoping to find a 'native' way to do the above but I failed so far to find one.
A 'native' way would be a factory like the 'wire' factory but instead of creating a child-context for each module, I'm looking to see the components of each module as direct components of the application context.
Spring, for instance, allows importing a context definition into another one and the result is as if the content of the imported context has been inlined with the importing context.
A new feature has been added to cujojs/wire to allow import of contexts.
As of version 0.10.8, the keyword imports accepts:
a string for a single context import,
or an array for a list of contexts import.
Check here for more details.

Associating an Object with other Objects and Properties of those Objects

I am looking for some help with designing some functionality in my application. I already have something similar designed but this problem is a little different.
Background:
In my application we have different Modules. Data in each module can be associated to other modules. Each Module is represented by an Object in our application.
Module 1 can be associated with Module 2 and Module 3. Currently I use a factory to provide the proper DAO for getting and saving this data.
It looks something like this:
class Module1Factory {
public static Module1BridgeDAO createModule1BridgeDAO(int moduleid) {
switch (moduleId)
{
case Module.Module2Id: return new Module1_Module2DAO();
case Module.Module3Id: return new Module1_Module3DAO();
default: return null;
}
}
}
Module1_Module2 and Module1_Module3 implement the same BridgeModule interface. In the database I have a Table for every module (Module1, Module2, Module3). I also have a bridge table for each module (they are many to many) Module1_Module2, Module1_Module3 etc.
The DAO basically handles all code needed to manage the association and retrieve its own instance data for the calling module. Now when we add new modules that associate with Module1 we simply implement the ModuleBridge interface and provide the common functionality.
New Development
We are adding a new module that will have the ability to be associated with other Modules as well as specific properties of that module. The module is basically providing the user the ability to add their custom forms to our other modules. That way they can collect additional information along with what we provide.
I want to start associating my Form module with other modules and their properties. Ie if Module1 has a property Category, I want to associate an instance From data with that property.
There are many Forms. If a users creates an instance of Module2, they may always want to also have certain form(s) attached to that Module2 instance. If they create an instance of Module2 and select Category 1, then I may want additional Form(s) created.
I prototyped something like this:
Form
FormLayout (contains the labels and gui controls)
FormModule (associates a form with all instances of a module)
Form Instance (create an instance of a form to be filled out)
As I thought about it I was thinking about making a new FormModule table/class/dao for each Module and Property that I add. So I might have:
FormModule1
FormModule1Property1
FormModule1Property2
FormModule1Property3
FormModule1Property4
FormModule2
FormModule3
FormModule3Property1
Then as I did previously, I would use a factory to get the proper DAO for dealing with all of these. I would hand it an array of ids representing different modules and properties and it would return all of the DAOs that I need to call getForms(). Which in turn would return all of the forms for that particular bridge.
Some points
This will be for a new module so I dont need to expand on the factory code I provided. I just wanted to show an example of what I have done in the past.
The new module can be associated with: Other Modules (ie globally for any instance of that module data), Other module properties (ie only if the Module instance has a certian value in one of its properties)
I want to make it easy for developers to add associations with other modules and properties easily
Can any one suggest any design patterns or strategy's for achieving this?
If anything is unclear please let me know.
Thank you,
Al
You can use springs Dependency Injection feature. This would help you achieve the flexibility of instantiating the objects using an xml configuration file.
So, my suggestion would be go with the Springs.