UNPKG

13.4 kBMarkdownView Raw
1# Concerto
2
3Concerto is a lightweight 100% JavaScript schema language and runtime. It works in both a Node.js process and in your browser. The browserified version of Concerto is ±280KB. We are working on making it even smaller.
4
5Things you can do using Concerto:
6- Define an object-oriented model using a domain-specific language that is much easier to read and write than JSON/XML Schema, XMI or equivalents. The metamodel gives you "just enough" expressivity to capture real-world business models, while remaining easy to map to most runtime environments.
7- Optionall edit your models using a powerful [VS Code add-on](https://marketplace.visualstudio.com/items?itemName=accordproject.cicero-vscode-extension) with syntax highlighting and validation
8- Create runtime instances of your model
9- Serialize your instances to JSON
10- Deserialize (and optionally validate) instances from JSON
11- Instances are JS objects so they are easy to pass around your application
12- Introspect the model using a powerful set of APIs
13- Convert the model to other formats: JSON Schema, XML Schema, Java, Go, Typescript, Loopback, PlantUML using [concerto-tools](https://github.com/accordproject/concerto-tools).
14- Import models from URLs
15- Publish your reusable models to any website, including the Accord Project Open Source model repository, hosted at: https://models.accordproject.org
16
17# Installation
18
19```
20npm install @accordproject/concerto --save
21```
22
23# Create a Concerto File
24
25```
26namespace org.acme.address
27
28/**
29 * This is a concept
30 */
31concept PostalAddress {
32 o String streetAddress optional
33 o String postalCode optional
34 o String postOfficeBoxNumber optional
35 o String addressRegion optional
36 o String addressLocality optional
37 o String addressCountry optional
38}
39```
40
41# Create a Model Manager
42
43```
44const ModelManager = require('@accordproject/concerto').ModelManager;
45
46const modelManager = new ModelManager();
47modelManager.addModelFile( concertoFileText, 'filename.cto');
48```
49
50# Create an Instance
51
52```
53const Factory = require('@accordproject/concerto').Factory;
54
55const factory = new Factory(modelManager);
56const postalAddress = factory.newConcept('org.acme.address', 'PostalAddress');
57postalAddress.streetAddress = '1 Maine Street';
58```
59
60# Serialize an Instance to JSON
61
62```
63const Serializer = require('@accordproject/concerto').Serializer;
64
65const serializer = new Serializer(factory, modelManager);
66const plainJsObject = serializer.toJSON(postalAddress); // instance will be validated
67console.log(JSON.stringify(plainJsObject, null, 4);
68```
69
70# Deserialize an Instance from JSON
71
72```
73const postalAddress = serializer.fromJSON(plainJsObject); // JSON will be validated
74console.log(postalAddress.streetAddress);
75```
76
77# Metamodel
78
79The Concerto metamodel contains:
80- Namespaces
81- Imports
82- Concepts
83- Assets
84- Participants
85- Transactions
86- Enumerations & Enumeration Values
87- Properties & Meta Properties
88- Relationships
89- Decorators
90
91## Namespaces
92
93```
94namespace foo
95```
96
97Every Concerto file starts with the name of a single namespace. All the definitions within a single file therefore belong to the same namespace. The `ModelManager` will refuse to load two model files that have the same namespace.
98
99## Imports
100
101To reference types defined in one namespace in another namespace the types must be imported.
102
103Imports can either be qualified, or can use wildcards.
104
105```
106import org.accordproject.address.PostalAddress
107```
108
109```
110import org.accordproject.address.*
111```
112
113Imports can also use the optional `from` declaration to import a model files that has been deployed to a URL.
114
115```
116import org.accordproject.address.PostalAddress from https://models.accordproject.org/address.cto
117```
118
119Imports that use a `from` declaration can be downloaded into the model manager by calling `modelManager.updateExternalModels`.
120
121The Model Manager will resolve all imports to ensure that the set of declarations that have been loaded are globally consistent.
122
123## Concepts
124
125Concepts are similar to class declarations in most object-oriented languages, in that they may have a super-type and a set of typed properties:
126
127```
128abstract concept Animal {
129 o DateTime dob
130}
131
132concept Dog extends Animal {
133 o String breed
134}
135```
136
137A concept can be declared `abstract` is it should not be instantiated (must be subclassed).
138
139## Assets
140
141An asset is a class declaration that has a single `String` property that acts as an identifier. Use the `modelManager.getAssetDeclarations` API to look up all assets.
142
143```
144asset Vehicle identified by vin {
145 o String vin
146}
147```
148
149Assets are typically used in your models for the long-lived identifiable Things (or nouns) in the model: cars, orders, shipping containers, products etc.
150
151## Participants
152
153An participant is a class declaration that has a single `String` property that acts as an identifier. Use the `modelManager.getParticipantDeclarations` API to look up all participants.
154
155```
156participant Customer identified by email {
157 o String email
158}
159```
160
161Participants are typically used in your models for the identifiable people or organizations in the model: person, customer, company, business, auditor etc.
162
163## Transactions
164
165An transaction is a class declaration that has a single `String` property that acts as an identifier. Use the `modelManager.getTransactionDeclarations` API to look up all transactions.
166
167```
168transaction Order identified by orderId {
169 o String orderId
170}
171```
172
173Transactions are typically used in your models for the identifiable business events or messages that are submitted by Participants to change the state of Assets: cart check out, change of address, identity verification, place order etc.
174
175## Enumerations & Enumeration Values
176
177Use enumerations to capture lists of domain values.
178
179```
180enum Gender {
181 o MALE
182 o FEMALE
183 o OTHER
184 o UNKNOWN
185}
186```
187
188## Properties and Meta Properties
189
190Class declarations contain properties. Each property has a type which can either be a type defined in the same namespace, an imported type or a primitive type.
191
192### Primitive types
193
194Concerto supports the following primitive types:
195- String: a UTF8 encoded String.
196- Double: a double precision 64 bit numeric value.
197- Integer: a 32 bit signed whole number.
198- Long: a 64 bit signed whole number.
199- DateTime: an ISO-8601 compatible time instance, with optional time zone and UTZ offset.
200- Boolean: a Boolean value, either true or false.
201
202### Meta Properties
203- [] : declares that the property is an array
204- optional : declares that the property is not required for the instance to be valid
205- default : declares a default value for the property, if not value is specified
206- range : declares a valid range for numeric properties
207- regex : declares a validation regex for string properties
208
209String fields may include an optional regular expression, which is used to validate the contents of the field. Careful use of field validators allows Concerto to perform rich data validation, leading to fewer errors and less boilerplate application code.
210
211The example below declares that the Farmer participant contains a field postcode that must conform to the regular expression for valid UK postcodes.
212
213```
214participant Farmer extends Participant {
215 o String firstName default="Old"
216 o String lastName default="McDonald"
217 o String address1
218 o String address2
219 o String county
220 o String postcode regex=/(GIR 0AA)|((([A-Z-[QVf]][0-9][0-9]?)|(([A-Z-[QVf]][A-Z-[IJZ]][0-9][0-9]?)|(([A-Z-[QVf]][0-9][A-HJKPSTUW])|([A-Z-[QVf]][A-Z-[IJZ]][0-9][ABEHMNPRVWfY])))) [0-9][A-Z-[CIKMOV]]{2})/
221}
222```
223
224Double, Long or Integer fields may include an optional range expression, which is used to validate the contents of the field.
225
226The example below declared that the Vehicle asset has an Integer field year which defaults to 2016 and must be 1990, or higher. Range expressions may omit the lower or upper bound if checking is not required.
227
228```
229asset Vehicle extends Base {
230 // An asset contains Fields, each of which can have an optional default value
231 o String model default="F150"
232 o String make default="FORD"
233 o String reg default="ABC123"
234 // A numeric field can have a range validation expression
235 o Integer year default=2016 range=[1990,] optional // model year must be 1990 or higher
236 o Integer[] integerArray
237 o State state
238 o Double value
239 o String colour
240 o String V5cID regex=/^[A-z][A-z][0-9]{7}/
241 o String LeaseContractID
242 o Boolean scrapped default=false
243 o DateTime lastUpdate optional
244 --> Participant owner //relationship to a Participant, with the field named 'owner'.
245 --> Participant[] previousOwners optional // Nary relationship
246 o Customer customer
247}
248```
249
250## Relationships
251
252A property of a class may be declared as a relationship using the `-->` syntax instead of the `o` syntax. The `o` syntax declares that the class contains (has-a) property of that type, whereas the `-->` syntax declares a typed pointer to an external identifiable instance.
253
254This model declares that an `Order` has-an array of `OrderLine` concepts. When the `Order` is deleted all the `OrderLines` will also be deleted.
255
256```
257concept OrderLine {
258 o String sku
259}
260asset Order identified by orderId {
261 o String orderId
262 o OrderLine[] orderlines
263}
264```
265
266Whereas this model declares that an `Order` has-an array of reference to `OrderLine`s. Deleting the `Order` has no impact on the `OrderLine`. When the `Order` is serialized the JSON only the IDs of the `OrderLines` are stored within the `Order`, not the `OrderLines` themselves.
267
268```
269asset OrderLine identified by orderLineId {
270 o String orderLineId
271 o String sku
272}
273
274asset Order identified by orderId {
275 o String orderId
276 --> OrderLine[] orderlines
277}
278```
279
280A relationship is a tuple composed of:
281
282The namespace of the type being referenced
283The type name of the type being referenced
284The identifier of the instance being referenced
285
286Hence a relationship could be to: `org.example.Vehicle#123456`
287
288This would be a relationship to the `Vehicle` type declared in the `org.example` namespace with the identifier `123456`.
289
290Relationships are unidirectional and deletes do not cascade, ie. removing the relationship has no impact on the thing that is being pointed to. Removing the thing being pointed to does not invalidate the relationship.
291
292Relationships must be resolved to retrieve an instance of the object being referenced. The act of resolution may result in null, if the object no longer exists or the information in the relationship is invalid. Resolution of relationships is outside of the scope of the Model Manager.
293
294## Decorators
295
296Model elements may have arbitrary decorators (aka annotations) placed on them. These are available via API and can be useful for tools to extend the model.
297
298```
299@foo("arg1", 2)
300asset Order identified by orderId {
301 o String orderId
302}
303```
304
305Decorators have an arbitrary number of arguments. They support arguments of type:
306- String
307- Boolean
308- Number
309- Type reference
310
311Resource definitions and properties may be decorated with 0 or more decorations. Note that only a single instance of a decorator is allowed on each element type. I.e. it is invalid to have the @bar decorator listed twice on the same element.
312
313Decorators are accessible at runtime via the `ModelManager` introspect APIs. This allows tools and utilities to use Concerto to describe a core model, while decorating it with sufficient metadata for their own purposes.
314
315The example below retrieves the 3rd argument to the foo decorator attached to the myField property of a class declaration:
316
317```
318const val = myField.getDecorator('foo').getArguments()[2];
319```
320
321## License <a name="license"></a>
322
323Accord Project source code files are made available under the [Apache License, Version 2.0][apache].
324Accord Project documentation files are made available under the [Creative Commons Attribution 4.0 International License][creativecommons] (CC-BY-4.0).
325
326Copyright 2018-2019 Clause, Inc. All trademarks are the property of their respective owners. See [LF Projects Trademark Policy](https://lfprojects.org/policies/trademark-policy/).
327
328[linuxfound]: https://www.linuxfoundation.org
329[charter]: https://github.com/accordproject/cicero/blob/master/CHARTER.md
330[apmain]: https://accordproject.org/
331[apworkgroup]: https://calendar.google.com/calendar/event?action=TEMPLATE&tmeid=MjZvYzIzZHVrYnI1aDVzbjZnMHJqYmtwaGlfMjAxNzExMTVUMjEwMDAwWiBkYW5AY2xhdXNlLmlv&tmsrc=dan%40clause.io
332[apblog]: https://medium.com/@accordhq
333[apnews]: https://www.accordproject.org/news/
334[apgit]: https://github.com/accordproject/
335[apdoc]: https://docs.accordproject.org/
336[apslack]: https://accord-project-slack-signup.herokuapp.com
337
338[docspec]: https://docs.accordproject.org/docs/spec-overview.html
339[docwelcome]: https://docs.accordproject.org/docs/accordproject.html
340[dochighlevel]: https://docs.accordproject.org/docs/spec-concepts.html
341[docergo]: https://docs.accordproject.org/docs/logic-ergo.html
342[docstart]: https://docs.accordproject.org/docs/accordproject.html
343[doccicero]: https://docs.accordproject.org/docs/basic-use.html
344[docstudio]: https://docs.accordproject.org/docs/advanced-latedelivery.html
345
346[contributing]: https://github.com/accordproject/cicero/blob/master/CONTRIBUTING.md
347[developers]: https://github.com/accordproject/cicero/blob/master/DEVELOPERS.md
348
349[apache]: https://github.com/accordproject/template-studio-v2/blob/master/LICENSE
350[creativecommons]: http://creativecommons.org/licenses/by/4.0/