I'd like to create a jsonschmema for a yaml file that will contain a list of defined keys to be referenced later in the yaml document.
example
myDef:
foo: bar
baz: lipsum
someProperty:
refferencedValue: foo
the schema should only validate values for someProperty.refferencedValue that are listed in myDef. So only foo and baz would be a valid someProperty.refferencedValue
is this possible with jsonschema? if so what would this look like?
In jsonschema it's not possible to reference arbitrary, dynamic values from the data to use it as part of the schema validation. See this discussion for more context. However:
If you can enumerate all possible properties (or property name patterns) of your myDef object, you can use oneOf to apply specific constraints on the someProperty.refferencedValue value for each property.
If you can't enumerate all the values you can't use standard jsonschema. Some validator libraries implement non-standard features that can help you. For example, Avj implements a $data keyword that can solve your issue. But keep in mind that this solution is tied to Avj - other validators will ignore this keyword.
Related
I am "playing" with graphql-java and the related kickstarter servlet, modifying it to build the schema programmatically based on the types I discover automatically. The documentation is (almost) there but is outdated in spots and references deprecated methods. My particular issue is that the GraphQLFieldDefinition.Builder has four variants of the type(...) method - three accepting various (other) builders and one accepting the GraphQLOutputType, none of which I may have. Furthermore, those that accept builder actually invoke the build() method on those builders so I am anxious to pass any of my "unfinished" type builders either. I thought of defining all types upfront with no fields at all, then add fields to them after that but if build() gets called on these at that point in time, even if they don't get into an unwanted state today I can see how a future update may demand at most a single build() invocation.
So the question is how does one declare a field to yet-undefined or not fully defined type? For example, an Employee's manager field being itself of the Employee type such as:
type Employee {
name: String!
manager: Employee
reports: [Employee!]
buddy: Employee
...
}
As I noted in my comments, instead of attempting to (directly) use the builder or the built type one should create an instance of GraphQLTypeReference instead like so:
GraphQLTypeReference.typeRef(typeName)
This will be resolved automatically when the schema is built.
Should we want to indicate that this is not nullable even if the referenced type is, we further need to wrap into a GraphQLNonNull wrapper like so:
GraphQLNonNull.nonNull(typeRef)
... and use that as the type.
In my use case I have a RAML 1.0 library created by our R&D department that contains definition of multiple data types. Those data types are defined in a generic, parametrized manner so when I reference them in my RAML I do so using following syntax:
type: { resourceTypes.collectionWithCriteria: {itemName: reward, itemCriteria: types.RewardCriteria, itemType : types.RewardList} }
This generates proper GET request with query string defined by types.RewardCriteria and response defined by types.RewardList. It also generates the description for the GET resource defined as: Retrieves the list of <<itemName | !pluralize>>, which ends up being Retrieves the list of rewards.
In my RAML I would like to append additional description to my GET resource, however I 'd rather avoid overwriting library-generated one. Is that possible? I've already tried inline description and using overlay file, both of which simply replace description from the library.
You cannot append for a single value simple property.
The merging rules for traits / resource types state that the description will be replaced:
Every explicit node wins over the ones that are declared in a resource
type or trait. The rest are simply merged.
Also, the merging rules of overlays and extensions states that:.
If the property is a Simple Property
If the property is a Single-value Simple Property,
The property value in the identically named Current Target Tree Object property is replaced with its value from Current Extension Tree Object property.
As specified in the docs and seen from the source code, SnakeYAML works with enums by their names. What I'd like to have is to parse values by enum value, e.g.:
Enum:
public enum Strategy {
ALWAYS_RUN("always-run"),
ALWAYS_SKIP("always-skip"),
DEPENDS("depends");
...
}
YAML:
branches:
trunk: always-skip
bugfix: depends
default: always-run
The reason is our code style forces us to use uppercase for enum constants, while I'd like to keep data in the yaml file lowercase.
As far as I am aware, this is not possible. Enum constants are private, and are therefore not accessible by other classes, so the YAML parser would not be able to construct the objects.
Although not perfect, you could use aliases to create a nickname for the enums.
There is another way to do this. Probably it's not clean but works properly.
Create a new Constructor class by extending org.yaml.snakeyaml.constructor.Constructor.
Inside it create a ScalarConstuctor protected class with the same code implementation as in base ScalarConstructor class except of enum parsing implementation.
In a method constructStandardJavaInstance check if an enum exists with uppercase or lowercase name.
Finally create Yaml object with the Constructor (of step 1)
I've been using mogenerator for a while now, and while there is a reasonable Getting Started Guide and a Stack Exchange article on the command line options, I haven't found a good guide for all of the functionality it provides.
In short: what, above and beyond the classes that Core Data provides for you, what does mogenerator actually generate?
(Frankly, I kept finding little pleasant surprises in the headers/implementations that I didn't realize were in there and I decided to step through the mogenerator templates and code and document what I found in a Stack Exchange Q&A. I'd love to see additional answers and edits, however. )
In addition to its core feature of a two class system, mogenerator helps you by automatically implementing a number of best practices regarding Core Data in your machine header and implementation files.
Property Accessors
Methods to access the attributes of your Entities are the core of what mogenerator generates. But there are some nice features implemented in the accessors above and beyond what the out of the box Xcode class generator provides to you.
Scalar Accessors
Xcode's built in generator gives you the option of "use scalar properties for primitive data types". This option gives you choice of having Xcode create properties with NSTimeIntervals instead of NSDates for date types, BOOLs instead of NSNumbers for boolean types, and int16_t (or similar) rather than NSNumbers.
I find this infuriating because most of the time I prefer the primitive types, but not for NSDates which are much more useful than a NSTimeInterval. So Core Data is giving me the choice of objects, in which case I will be constantly unboxing stuff and making stupid mistakes like if(myBooleanAttribute) (which is always YES because myBooleanAttribute is a NSNumber, not a BOOL). Or I can have scalars, but in that case, I get NSTimeIntervals that I'll always have to convert to NSDates. Or I can hand edit all of the generated files by hand to give me my desired mix of NSDates and BOOLs.
On the other hand, mogenerator provides you with both options. For example, you will get both a myBooleanAttribute getter that gives you an NSNumber (for easy storage in an NSArray) and a myBooleanAttributeValue getter that gives you an actual BOOL. Same with integers and floats. (Mogenerator does not generate NSTimeInterval accessors: only NSDates.)
Typed Transformable Properties
If you have a transformable property, you can set a specific UserInfo key ( attributeValueClassName ) in the attribute that will specify the class that your property will return/accept. (And it will properly forward declare the class etc.) The only place I found this documented was on Verious.
In contrast, the Xcode code generator will only type these transformable attributes as id types.
Validation Declaration
While mogenerator does not automatically generate any validation methods, it does include the proper signature as a comment in the machine h file. The seems to largely be for historical reasons, but it does mean that it is easy to copy and paste the signature if you decide to implement it in your human file implementation. (I wouldn't actually uncomment the declaration as you aren't supposed to call validation directly.)
Primitive Accessors
Core Data already provides you these accessors to the primitive values, but for some reason doesn't include them in its Xcode generated headers. Having mogenerator include them in its header files makes it much easier to access a primitive value.
Fetched Properties
mogenerator will generate accessors for fetched properties. As far as I can tell there is no way to have the Xcode generator do this.
Helper methods
Automatic NSFetchedResultsController generation
If you have a to many relationship in your Entity and you pass --template-var frc=true into mogenerator, mogenerator will automatically generate a method to create a fetch request for the child objects associated with a parent object. It even automatically generates a unique cache name, and isolates everything inside an #if TARGET_OS_IPHONE preprocessor macro.
Even if this doesn't fit your particular needs, it is a great example of how the templates can be extended.
+fetchMyFetchRequest:moc_
If you like defining your fetch requests in the model, this is a lot better way to retrieve them than hardcoded strings.
-MyEntitySet
Mogenerator uses the magic of KVC to give you a NSMutableSet proxy into your relationships.
+entityName
Need to provide a entity name to a NSFetchRequest or other Core Data method? It's easy to avoid hard coded strings by using this simple method that returns the name of the entity as an NSString.
+insertInManagedObjectContext: and entityInManagedObjectContext:
Another way to avoid hardcoding entity names is to use these helper methods.
Typed object ids
Each of your headers and implementations also includes a MyEntityID class. They are empty interfaces and implementations that merely subclass the NSManagedObjectID class. Also, each model class has a helper method called objectID that overrides the standard objectID method in NSManagedObject. The helper method does nothing but cast the superclass's return value to the MyEntityID type.
The net result: the compiler can catch your mistakes if you ever accidentally interchange your object ids from different entities.
Miscellaneous
Subclassing a Custom Superclass
One of the command line options is --base-class: which allows you to specify a base class that all of your generated classes will inherit from. This is very useful, either so that you can have a base class where you define convenience methods (which, given Core Data, you probably should) or so you can use an off the shelf Core Data toolkit like SSDataKit (or both).
includem
A simple little thing, but if you specify a --includem argument, mogenerator will generate a header file that includes all of your model header files. Convenient if you want to include all of your headers in a PCH, or something some other standard header you include.
Const Definitions of All Attributes, Relationships, Fetched Properties
An extern declaration of a struct is included in the header that has an NSString defined for every attribute and relationship defined in your Entity. This allows you to define predicates and other parameters, without baking the names of your entities into your strings. For example,
req.predicate = [NSPredicate predicateWithFormat:
#"(%K == YES) AND (%K <= %#)",MyObject.favorite, MyObject.availableDate, [NSDate date]];
(This type of struct used for "namespaced" constants is described My Mike Ash on his blog
const Definitions of User Info Keys/Values
Similarly an extern declaration of a struct is defined in the header that includes the keys as members of the struct, and the values as a values. i.e.
NSLog(#"User info for key my key is %#",MyObjectInfo.mykey) //will log "myvalue"
Alternate Templates
One of the interesting things about mogenerator is that in building mogenerator its author (Wolf Rentzsch) has basically built a generic parser and templating engine for the xcdatamodel files produced by Xcode. So you don't need to use the mogenerator templates. You can provide your own with a simple command line argument. There are lots of user contributed templates on the GitHub site.
In fact, you don't even have to use Core Data. Many of the contributed templates allow you to generate a series of ordinary NSObject model classes based on the data model. (So called PONSOs: "plain old nsobjects"). Want to use the data modeler in Xcode, but some other persistence mechanism? mogenerator can help you there.
You don't even need to generate objects at all: another interesting submitted template just provides a diff of two different model versions.
Help! My fingers are falling off from typing so much.
I have a lot of objects that have sane names to them. The Database names are not so sane, and i'm stuck defining my property names in all my projections.
For example:
from f in foo select new MyClass() {MyID = f.ID, MyName = f.f, MyTime = f.t}
Etc.. now, multiply this by hundreds or even thousands of business object methods that materialize data into various classes with mismatched field names and and dozens of properties in most fields andit's a lot of typing.
So, i'm wondering if there is any way (maybe via Attributes or something else) that allows you to define a default mapping for the class so that even if the fields mismatch I can simply say:
from f in foo select new MyClass()
Any solutions? Or am I stuck typing my fingers off?
EDIT:
Upon further reflection (pun semi-intended), I realize that this is precisely what L2S is for, and I can rename the fields in the L2S Data classes to whatever I need.
Sometimes the easiest answers are right in front of us.
Well, one obvious option is to go to the DBML designer and change the names of the properties in the generated classes. They don't have to be the same as the ones in the database.
Just go into the designer, click on a property and change the Name part. (The Source property is the database column name.) Rebuild the project, and the names will have changed.
Alternatively, if you're always transforming from one source into the same type, create a method in a partial class for the source data type which transforms into the target one - or vice versa. So you could write a Foo.ToMyClass() method, or MyClass.FromFoo(Foo foo).
Just one other suggestion - AutoMapper would allow you to register mappings once and then just call a shared method to map from one object to another