Update license date and text
[aai/champ.git] / champ-lib / champ-core / src / test / java / org / onap / aai / champcore / core / ChampSchemaTest.java
1 /**
2  * ============LICENSE_START==========================================
3  * org.onap.aai
4  * ===================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 Amdocs
7  * ===================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *        http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END============================================
20  */
21 package org.onap.aai.champcore.core;
22
23 import static org.junit.Assert.assertTrue;
24
25 import java.io.IOException;
26 import java.util.Optional;
27 import java.util.Set;
28
29 import org.junit.Test;
30 import org.onap.aai.champcore.ChampAPI;
31 import org.onap.aai.champcore.ChampGraph;
32 import org.onap.aai.champcore.exceptions.ChampMarshallingException;
33 import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException;
34 import org.onap.aai.champcore.exceptions.ChampSchemaViolationException;
35 import org.onap.aai.champcore.exceptions.ChampTransactionException;
36 import org.onap.aai.champcore.model.ChampConnectionConstraint;
37 import org.onap.aai.champcore.model.ChampConnectionMultiplicity;
38 import org.onap.aai.champcore.model.ChampField;
39 import org.onap.aai.champcore.model.ChampObject;
40 import org.onap.aai.champcore.model.ChampObject.ReservedTypes;
41 import org.onap.aai.champcore.model.ChampObjectConstraint;
42 import org.onap.aai.champcore.model.ChampPartition;
43 import org.onap.aai.champcore.model.ChampPropertyConstraint;
44 import org.onap.aai.champcore.model.ChampRelationship;
45 import org.onap.aai.champcore.model.ChampRelationshipConstraint;
46 import org.onap.aai.champcore.model.ChampSchema;
47 import org.onap.aai.champcore.schema.AlwaysValidChampSchemaEnforcer;
48 import org.onap.aai.champcore.schema.ChampSchemaEnforcer;
49 import org.onap.aai.champcore.schema.DefaultChampSchemaEnforcer;
50
51 import com.fasterxml.jackson.databind.ObjectMapper;
52
53 public class ChampSchemaTest extends BaseChampAPITest {
54
55         @Test
56         public void runInMemoryTest() {
57                 runTest("IN_MEMORY");
58         }
59
60         public void runTest(String apiType) {
61                         final String graphName = ChampSchemaTest.class.getSimpleName();
62
63                         final ChampAPI api = ChampAPI.Factory.newInstance(apiType);
64
65                         try {
66                                 ChampSchemaTest.testChampSchemaCrud(api.getGraph(graphName));
67                         } catch (Throwable t) {
68                                 throw new AssertionError(apiType + " unit test failed", t);
69                         }
70
71                         api.shutdown();
72         }
73
74         public static void testChampSchemaCrud(ChampGraph graph) {
75
76                 final ChampSchema schema = ChampSchema.create()
77                                         .withObjectConstraint()
78                                                 .onType("foo")
79                                                 .withPropertyConstraint()
80                                                         .onField("property1")
81                                                         .required()
82                                                         .build()
83                                                 .withPropertyConstraint()
84                                                         .onField("property2")
85                                                         .optional()
86                                                         .build()
87                                                 .build()
88                                         .withRelationshipConstraint()
89                                                 .onType("bar")
90                                                 .withPropertyConstraint()
91                                                         .onField("at")
92                                                         .ofType(ChampField.Type.STRING)
93                                                         .optional()
94                                                         .build()
95                                                 .withConnectionConstraint()
96                                                         .sourcedFrom("foo")
97                                                         .targetedToAny()
98                                                         .build()
99                                                 .build()
100                                         .build();
101
102                 try {
103                         graph.storeSchema(schema);
104                 } catch (ChampSchemaViolationException e) {
105                         throw new AssertionError(e);
106                 }
107
108                 final ChampObject emptyFoo = ChampObject.create()
109                                                                                                 .ofType("foo")
110                                                                                                 .withoutKey()
111                                                                                                 .build();
112
113                 try {
114                         graph.storeObject(emptyFoo, Optional.empty());
115                 } catch (ChampMarshallingException e1) {
116                         throw new AssertionError(e1);
117                 } catch (ChampSchemaViolationException e1) {
118                         //Expected, since it does not have the required property "property1"
119                 } catch (ChampObjectNotExistsException e) {
120                         throw new AssertionError(e);
121                 } catch (ChampTransactionException e) {
122                   throw new AssertionError(e);
123         }
124
125                 final ChampSchema retrievedSchema = graph.retrieveSchema();
126
127                 if (!schema.equals(retrievedSchema)) throw new AssertionError("Retrieved schema is not the same as the schema that was previously stored");
128
129                 try {
130                         graph.updateSchema(new ChampRelationshipConstraint.Builder("bard").build());
131                         assertTrue(graph.retrieveSchema().getRelationshipConstraint("bard").isPresent());
132
133                         graph.updateSchema(new ChampObjectConstraint.Builder("baz").build());
134                         assertTrue(graph.retrieveSchema().getObjectConstraint("baz").isPresent());
135                 } catch (ChampSchemaViolationException e) {
136                         throw new AssertionError(e);
137                 }
138
139                 final ChampSchema updatedSchema = graph.retrieveSchema();
140
141                 if (!updatedSchema.getObjectConstraint("baz").isPresent()) throw new AssertionError("Updated schema and retrieved, but retrieved schema did not contain updates");
142                 if (!updatedSchema.getRelationshipConstraint("bard").isPresent()) throw new AssertionError("Updated schema and retrieved, but retrieved schema did not contain updates");
143
144                 try {
145                         graph.updateSchema(new ChampObjectConstraint.Builder("foo")
146                                                                                                                 .constraint(
147                                                                                                                         new ChampPropertyConstraint.Builder(
148                                                                                                                                 new ChampField.Builder("property2")
149                                                                                                                                                                 .build()
150                                                                                                                         )
151                                                                                                                         .required(false)
152                                                                                                                         .build()
153                                                                                                                 )
154                                                                                                                 .build());
155
156                         final ChampObject storedEmptyFoo = graph.storeObject(emptyFoo, Optional.empty());
157                         
158                         graph.deleteObject(storedEmptyFoo.getKey().get(), Optional.empty());
159                 } catch (ChampMarshallingException e) {
160                         throw new AssertionError(e);
161                 } catch (ChampSchemaViolationException e) {
162                         throw new AssertionError(e);
163                 } catch (ChampObjectNotExistsException e) {
164                         throw new AssertionError(e);
165                 } catch (ChampTransactionException e) {
166                   throw new AssertionError(e);
167         }
168                 
169                 graph.deleteSchema();
170                 assertTrue(graph.retrieveSchema().equals(ChampSchema.emptySchema()));
171         }
172
173         @Test
174         public void testChampSchemaFluentApi() {
175                 final ChampSchema schema = ChampSchema.create()
176                                         .withObjectConstraint()
177                                                 .onType("foo")
178                                                 .withPropertyConstraint()
179                                                         .onField("bar")
180                                                         .ofType(ChampField.Type.STRING)
181                                                         .required()
182                                                         .build()
183                                                 .withPropertyConstraint()
184                                                         .onField("baz")
185                                                         .ofType(ChampField.Type.BOOLEAN)
186                                                         .optional()
187                                                         .build()
188                                                 .build()
189                                         .withRelationshipConstraint()
190                                                 .onType("eats")
191                                                 .withPropertyConstraint()
192                                                         .onField("at")
193                                                         .ofType(ChampField.Type.STRING)
194                                                         .required()
195                                                         .build()
196                                                 .withPropertyConstraint()
197                                                         .onField("for")
198                                                         .optional()
199                                                         .build()
200                                                 .withConnectionConstraint()
201                                                         .sourcedFrom("foo")
202                                                         .targetedTo("foo")
203                                                         .withMultiplicity(ChampConnectionMultiplicity.ONE)
204                                                         .build()
205                                                 .withConnectionConstraint()
206                                                         .sourcedFrom("bar")
207                                                         .targetedTo("bar")
208                                                         .build()
209                                         .build()
210                                 .build();
211
212                 assertTrue(schema.getObjectConstraint("foo").get().getType().equals("foo"));
213                 
214                 for (ChampPropertyConstraint propConst : schema.getObjectConstraint("foo").get().getPropertyConstraints()) {
215                         if (propConst.getField().getName().equals("bar")) {
216                                 assertTrue(propConst.getField().getJavaType().equals(String.class));
217                                 assertTrue(propConst.isRequired());
218                         } else if (propConst.getField().getName().equals("baz")) {
219                                 assertTrue(propConst.getField().getJavaType().equals(Boolean.class));
220                                 assertTrue(!propConst.isRequired());
221                         } else {
222                                 throw new AssertionError("Unknown property constraint found: " + propConst);
223                         }
224                 }
225
226                 assertTrue(schema.getRelationshipConstraint("eats").get().getType().equals("eats"));
227
228                 for (ChampPropertyConstraint propConst : schema.getRelationshipConstraint("eats").get().getPropertyConstraints()) {
229                         if (propConst.getField().getName().equals("at")) {
230                                 assertTrue(propConst.getField().getJavaType().equals(String.class));
231                                 assertTrue(propConst.isRequired());
232                         } else if (propConst.getField().getName().equals("for")) {
233                                 assertTrue(propConst.getField().getJavaType().equals(String.class));
234                                 assertTrue(!propConst.isRequired());
235                         } else {
236                                 throw new AssertionError("Unknown property constraint found: " + propConst);
237                         }
238                 }
239
240                 for (ChampConnectionConstraint connConst : schema.getRelationshipConstraint("eats").get().getConnectionConstraints()) {
241                         if (connConst.getSourceType().equals("foo")) {
242                                 assertTrue(connConst.getTargetType().equals("foo"));
243                                 assertTrue(connConst.getMultiplicity() == ChampConnectionMultiplicity.ONE);
244                         } else if (connConst.getSourceType().equals("bar")) {
245                                 assertTrue(connConst.getTargetType().equals("bar"));
246                                 assertTrue(connConst.getMultiplicity() == ChampConnectionMultiplicity.MANY);
247                         } else {
248                                 throw new AssertionError("Unknown connection constraint found: " + connConst);
249                         }
250                 }
251         }
252
253         @Test
254         public void testDefaultChampSchemaEnforcer() {
255
256                 final ChampSchemaEnforcer schemaEnforcer = new DefaultChampSchemaEnforcer();
257                 final ChampSchema champSchema = ChampSchema.create()
258                                                                                         .withObjectConstraint()
259                                                                                                 .onType("foo")
260                                                                                                 .withPropertyConstraint()
261                                                                                                         .onField("bar")
262                                                                                                         .ofType(ChampField.Type.STRING)
263                                                                                                         .required()
264                                                                                                         .build()
265                                                                                                 .build()
266                                                                                         .withRelationshipConstraint()
267                                                                                                 .onType("makes")
268                                                                                                 .withPropertyConstraint()
269                                                                                                         .onField("bar")
270                                                                                                         .required()
271                                                                                                         .build()
272                                                                                                 .withConnectionConstraint()
273                                                                                                         .sourcedFrom("foo")
274                                                                                                         .targetedTo("fiz")
275                                                                                                         .withMultiplicity(ChampConnectionMultiplicity.ONE)
276                                                                                                         .build()
277                                                                                                 .build()
278                                                                                         .build();
279
280                 try {
281                         schemaEnforcer.validate(ChampObject.create()
282                                                                                                 .ofType("foo")
283                                                                                                 .withoutKey()
284                                                                                                 .withProperty("bar", "true")
285                                                                                                 .build(),
286                                                                         champSchema.getObjectConstraint("foo").get());
287                 } catch (ChampSchemaViolationException e) {
288                         throw new AssertionError(e);
289                 }
290
291                 try {
292                         schemaEnforcer.validate(ChampObject.create()
293                                                                                                 .ofType("foo")
294                                                                                                 .withoutKey()
295                                                                                                 .build(),
296                                                                         champSchema.getObjectConstraint("foo").get());
297                         throw new AssertionError("Failed to enforce required property constraint on object");
298                 } catch (ChampSchemaViolationException e) {
299                         //Expected
300                 }
301
302                 try {
303                         schemaEnforcer.validate(ChampObject.create()
304                                                                                                 .ofType("foo")
305                                                                                                 .withoutKey()
306                                                                                                 .withProperty("bar", true)
307                                                                                                 .build(),
308                                                                         champSchema.getObjectConstraint("foo").get());
309                         throw new AssertionError("Failed to enforce property type constraint on object");
310                 } catch (ChampSchemaViolationException e) {
311                         //Expected
312                 }
313
314                 try {
315                         schemaEnforcer.validate(ChampRelationship.create()
316                                                                                                 .ofType("makes")
317                                                                                                 .withoutKey()
318                                                                                                 .withSource()
319                                                                                                         .ofType("foo")
320                                                                                                         .withoutKey()
321                                                                                                         .build()
322                                                                                                 .withTarget()
323                                                                                                         .ofType("fiz")
324                                                                                                         .withoutKey()
325                                                                                                         .build()
326                                                                                                 .withProperty("bar", "true")
327                                                                                                 .build(),
328                                                                         champSchema.getRelationshipConstraint("makes").get()
329                                                                 );
330                 } catch (ChampSchemaViolationException e) {
331                         throw new AssertionError(e);
332                 }
333
334                 try {
335                         schemaEnforcer.validate(ChampRelationship.create()
336                                                                                                                 .ofType("makes")
337                                                                                                                 .withoutKey()
338                                                                                                                 .withSource()
339                                                                                                                         .ofType("foo")
340                                                                                                                         .withoutKey()
341                                                                                                                         .build()
342                                                                                                                 .withTarget()
343                                                                                                                         .ofType("fiz")
344                                                                                                                         .withoutKey()
345                                                                                                                         .build()
346                                                                                                                 .build(),
347                                                                         champSchema.getRelationshipConstraint("makes").get()
348                                                                 );
349                         throw new AssertionError("Failed to enforce required property constraint on relationship");
350                 } catch (ChampSchemaViolationException e) {
351                         //Expected
352                 }
353
354                 try {
355                         schemaEnforcer.validate(ChampPartition.create()
356                                                                                                 .withObject(
357                                                                                                         ChampObject.create()
358                                                                                                                                 .ofType("foo")
359                                                                                                                                 .withoutKey()
360                                                                                                                                 .withProperty("bar", "true")
361                                                                                                                                 .build()
362                                                                                                 )
363                                                                                                 .withObject(
364                                                                                                         ChampObject.create()
365                                                                                                                                 .ofType("fiz")
366                                                                                                                                 .withoutKey()
367                                                                                                                                 .build()
368                                                                                                 )
369                                                                                                 .withRelationship(
370                                                                                                         ChampRelationship.create()
371                                                                                                                                                 .ofType("makes")
372                                                                                                                                                 .withoutKey()
373                                                                                                                                                 .withSource()
374                                                                                                                                                         .ofType("foo")
375                                                                                                                                                         .withoutKey()
376                                                                                                                                                         .withProperty("bar", "true")
377                                                                                                                                                         .build()
378                                                                                                                                                 .withTarget()
379                                                                                                                                                         .ofType("fiz")
380                                                                                                                                                         .withoutKey()
381                                                                                                                                                         .build()
382                                                                                                                                                 .withProperty("bar",  "true")
383                                                                                                                                                 .build()
384                                                                                                 )
385                                                                                                 .withRelationship(
386                                                                                                         ChampRelationship.create()
387                                                                                                                                                 .ofType("makes")
388                                                                                                                                                 .withoutKey()
389                                                                                                                                                 .withSource()
390                                                                                                                                                         .ofType("fiz")
391                                                                                                                                                         .withoutKey()
392                                                                                                                                                         .build()
393                                                                                                                                                 .withTarget()
394                                                                                                                                                         .ofType("foo")
395                                                                                                                                                         .withoutKey()
396                                                                                                                                                         .withProperty("bar", "true")
397                                                                                                                                                         .build()
398                                                                                                                                                 .withProperty("bar", "true")
399                                                                                                                                                 .build()
400                                                                                                 )
401                                                                                                 .build(),
402                                                                                                 champSchema                                     
403                                                                 );
404                 } catch (ChampSchemaViolationException e) {
405                         throw new AssertionError(e);
406                 }
407
408                 try {
409                         schemaEnforcer.validate(ChampPartition.create()
410                                                                                                 .withObject(
411                                                                                                         ChampObject.create()
412                                                                                                                                 .ofType("foo")
413                                                                                                                                 .withoutKey()
414                                                                                                                                 .withProperty("bar", "true")
415                                                                                                                                 .build()
416                                                                                                 )
417                                                                                                 .withObject(
418                                                                                                         ChampObject.create()
419                                                                                                                                 .ofType("fiz")
420                                                                                                                                 .withoutKey()
421                                                                                                                                 .build()
422                                                                                                 )
423                                                                                                 .withRelationship(
424                                                                                                         ChampRelationship.create()
425                                                                                                                                                 .ofType("makes")
426                                                                                                                                                 .withoutKey()
427                                                                                                                                                 .withSource()
428                                                                                                                                                         .ofType("foo")
429                                                                                                                                                         .withoutKey()
430                                                                                                                                                         .withProperty("bar", "true")
431                                                                                                                                                         .build()
432                                                                                                                                                 .withTarget()
433                                                                                                                                                         .ofType("fiz")
434                                                                                                                                                         .withoutKey()
435                                                                                                                                                         .build()
436                                                                                                                                                 .withProperty("bar",  "true")
437                                                                                                                                                 .build()
438                                                                                                 )
439                                                                                                 .withRelationship(
440                                                                                                         ChampRelationship.create()
441                                                                                                                                                 .ofType("makes")
442                                                                                                                                                 .withoutKey()
443                                                                                                                                                 .withSource()
444                                                                                                                                                         .ofType("foo")
445                                                                                                                                                         .withoutKey()
446                                                                                                                                                         .withProperty("bar", "true")
447                                                                                                                                                         .build()
448                                                                                                                                                 .withTarget()
449                                                                                                                                                         .ofType("fiz")
450                                                                                                                                                         .withoutKey()
451                                                                                                                                                         .build()
452                                                                                                                                                 .withProperty("bar", "true")
453                                                                                                                                                 .build()
454                                                                                                 )
455                                                                                                 .build(),
456                                                                                                 champSchema                                     
457                                                                 );
458                         throw new AssertionError("Failed to enforce connection constraint on relationship type 'makes'");
459                 } catch (ChampSchemaViolationException e) {
460                         //Expected
461                 }
462         }
463
464         @Test
465         public void testAlwaysValidChampSchemaEnforcer() {
466
467                 final ChampSchemaEnforcer schemaEnforcer = new AlwaysValidChampSchemaEnforcer();
468
469                 try {
470                         schemaEnforcer.validate(ChampObject.create()
471                                                                                                 .ofType("foo")
472                                                                                                 .withoutKey()
473                                                                                                 .withProperty("bar", true)
474                                                                                                 .build(),
475                                                                         new ChampObjectConstraint.Builder("foo")
476                                                                                                                                 .constraint(
477                                                                                                                                         new ChampPropertyConstraint.Builder(
478                                                                                                                                                 new ChampField.Builder("bar")
479                                                                                                                                                                                 .type(ChampField.Type.STRING)
480                                                                                                                                                                                 .build()
481                                                                                                                                         )
482                                                                                                                                         .required(true)
483                                                                                                                                         .build()
484                                                                                                                                 )
485                                                                                                                                 .build()
486                                                                 );
487
488                         schemaEnforcer.validate(ChampRelationship.create()
489                                                                                                 .ofType("foo")
490                                                                                                 .withoutKey()
491                                                                                                 .withSource()
492                                                                                                         .ofType("foo")
493                                                                                                         .withoutKey()
494                                                                                                         .build()
495                                                                                                 .withTarget()
496                                                                                                         .ofType("fiz")
497                                                                                                         .withoutKey()
498                                                                                                         .build()
499                                                                                                 .withProperty("bar", true)
500                                                                                                 .build(),
501                                                                         new ChampRelationshipConstraint.Builder("bar")
502                                                                                                                                 .constraint(
503                                                                                                                                         new ChampPropertyConstraint.Builder(
504                                                                                                                                                 new ChampField.Builder("bar")
505                                                                                                                                                                                 .type(ChampField.Type.STRING)
506                                                                                                                                                                                 .build()
507                                                                                                                                         )
508                                                                                                                                         .required(true)
509                                                                                                                                         .build()
510                                                                                                                                 )
511                                                                                                                                 .build()
512                                                                 );
513
514                         schemaEnforcer.validate(ChampPartition.create()
515                                                                                                 .withObject(
516                                                                                                         ChampObject.create()
517                                                                                                                                 .ofType("foo")
518                                                                                                                                 .withoutKey()
519                                                                                                                                 .withProperty("bar", true)
520                                                                                                                                 .build()
521                                                                                                 )
522                                                                                                 .withObject(
523                                                                                                         ChampObject.create()
524                                                                                                                                 .ofType("fiz")
525                                                                                                                                 .withoutKey()
526                                                                                                                                 .withProperty("bar", true)
527                                                                                                                                 .build()
528                                                                                                 )
529                                                                                                 .withRelationship(
530                                                                                                         ChampRelationship.create()
531                                                                                                                                                 .ofType("makes")
532                                                                                                                                                 .withoutKey()
533                                                                                                                                                 .withSource()
534                                                                                                                                                         .ofType("foo")
535                                                                                                                                                         .withoutKey()
536                                                                                                                                                         .build()
537                                                                                                                                                 .withTarget()
538                                                                                                                                                         .ofType("fiz")
539                                                                                                                                                         .withoutKey()
540                                                                                                                                                         .build()
541                                                                                                                                                 .build()
542                                                                                                 )
543                                                                                                 .withRelationship(
544                                                                                                         ChampRelationship.create()
545                                                                                                                                                 .ofType("makes")
546                                                                                                                                                 .withoutKey()
547                                                                                                                                                 .withSource()
548                                                                                                                                                         .ofType("foo")
549                                                                                                                                                         .withoutKey()
550                                                                                                                                                         .build()
551                                                                                                                                                 .withTarget()
552                                                                                                                                                         .ofType("fiz")
553                                                                                                                                                         .withoutKey()
554                                                                                                                                                         .build()
555                                                                                                                                                 .withProperty("bar", true)
556                                                                                                                                                 .build()
557                                                                                                 )
558                                                                                                 .build(),
559                                                                 ChampSchema.create()
560                                                                                         .withObjectConstraint()
561                                                                                                 .onType("foo")
562                                                                                                 .withPropertyConstraint()
563                                                                                                         .onField("bar")
564                                                                                                         .required()
565                                                                                                         .build()
566                                                                                                 .build()
567                                                                                         .withRelationshipConstraint()
568                                                                                                 .onType("makes")
569                                                                                                 .withPropertyConstraint()
570                                                                                                         .onField("bar")
571                                                                                                         .required()
572                                                                                                         .build()
573                                                                                                 .withConnectionConstraint()
574                                                                                                         .sourcedFrom("foo")
575                                                                                                         .targetedTo("fiz")
576                                                                                                         .withMultiplicity(ChampConnectionMultiplicity.ONE)
577                                                                                                         .build()
578                                                                                                 .build()
579                                                                                         .withRelationshipConstraint()
580                                                                                                 .onType("uses")
581                                                                                                 .withConnectionConstraint()
582                                                                                                         .sourcedFromAny()
583                                                                                                         .targetedTo("computer")
584                                                                                                         .build()
585                                                                                                 .build()
586                                                                                         .withRelationshipConstraint()
587                                                                                                 .onType("destroys")
588                                                                                                 .withConnectionConstraint()
589                                                                                                         .sourcedFrom("computer")
590                                                                                                         .targetedToAny()
591                                                                                                         .build()
592                                                                                                 .build()
593                                                                                         .build()
594                                                                                                         
595                                                                 );
596                 } catch (ChampSchemaViolationException e) {
597                         throw new AssertionError(e);
598                 }
599         }
600
601         @Test
602         public void testFluentSchemaApi() {
603                 final ChampSchema schema = ChampSchema.create()
604                                                                                                 .withObjectConstraint()
605                                                                                                         .onType("a")
606                                                                                                         .withPropertyConstraint()
607                                                                                                                 .onField("z")
608                                                                                                                 .ofType(ChampField.Type.STRING)
609                                                                                                                 .optional()
610                                                                                                                 .build()
611                                                                                                         .build()
612                                                                                                 .withObjectConstraint()
613                                                                                                         .onType("b")
614                                                                                                         .withPropertyConstraint()
615                                                                                                                 .onField("y")
616                                                                                                                 .ofType(ChampField.Type.LONG)
617                                                                                                                 .required()
618                                                                                                                 .build()
619                                                                                                         .build()
620                                                                                                 .withRelationshipConstraint()
621                                                                                                         .onType("one")
622                                                                                                         .withPropertyConstraint()
623                                                                                                                 .onField("nine")
624                                                                                                                 .ofType(ChampField.Type.INTEGER)
625                                                                                                                 .optional()
626                                                                                                                 .build()
627                                                                                                         .withConnectionConstraint()
628                                                                                                                 .sourcedFrom("a")
629                                                                                                                 .targetedTo("b")
630                                                                                                                 .withMultiplicity(ChampConnectionMultiplicity.NONE)
631                                                                                                                 .build()
632                                                                                                         .withConnectionConstraint()
633                                                                                                                 .sourcedFrom("a")
634                                                                                                                 .targetedToAny()
635                                                                                                                 .withMultiplicity(ChampConnectionMultiplicity.ONE)
636                                                                                                                 .build()
637                                                                                                         .withConnectionConstraint()
638                                                                                                                 .sourcedFromAny()
639                                                                                                                 .targetedTo("b")
640                                                                                                                 .withMultiplicity(ChampConnectionMultiplicity.MANY)
641                                                                                                                 .build()
642                                                                                                         .withConnectionConstraint()
643                                                                                                                 .sourcedFromAny()
644                                                                                                                 .targetedToAny()
645                                                                                                                 .withMultiplicity(ChampConnectionMultiplicity.MANY)
646                                                                                                                 .build()
647                                                                                                         .build()
648                                                                                                 .build();
649
650                 final ChampObjectConstraint aObjConstraint = schema.getObjectConstraint("a").get();
651
652                 assertTrue(aObjConstraint.getType().equals("a"));
653
654                 final ChampPropertyConstraint zPropertyConstraint = aObjConstraint.getPropertyConstraint("z").get();
655
656                 assertTrue(zPropertyConstraint.getField().getName().equals("z"));
657                 assertTrue(zPropertyConstraint.getField().getJavaType().equals(String.class));
658                 assertTrue(!zPropertyConstraint.isRequired());
659
660                 final ChampObjectConstraint bObjConstraint = schema.getObjectConstraint("b").get();
661
662                 assertTrue(bObjConstraint.getType().equals("b"));
663
664                 final ChampPropertyConstraint yPropertyConstraint = bObjConstraint.getPropertyConstraint("y").get();
665
666                 assertTrue(yPropertyConstraint.getField().getName().equals("y"));
667                 assertTrue(yPropertyConstraint.getField().getJavaType().equals(Long.class));
668                 assertTrue(yPropertyConstraint.isRequired());
669
670                 final ChampRelationshipConstraint oneRelConstraint = schema.getRelationshipConstraint("one").get();
671
672                 assertTrue(oneRelConstraint.getType().equals("one"));
673
674                 final ChampPropertyConstraint ninePropertyConstraint = oneRelConstraint.getPropertyConstraint("nine").get();
675
676                 assertTrue(ninePropertyConstraint.getField().getName().equals("nine"));
677                 assertTrue(ninePropertyConstraint.getField().getJavaType().equals(Integer.class));
678                 assertTrue(!ninePropertyConstraint.isRequired());
679
680                 final Set<ChampConnectionConstraint> connectionConstraints = oneRelConstraint.getConnectionConstraints();
681
682                 for (ChampConnectionConstraint cc : connectionConstraints) {
683                         if (cc.getSourceType().equals("a") && cc.getTargetType().equals("b")) {
684                                 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.NONE);
685                         } else if (cc.getSourceType().equals(ReservedTypes.ANY.toString()) && cc.getTargetType().equals("b")) {
686                                 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.MANY);
687                         } else if (cc.getSourceType().equals(ReservedTypes.ANY.toString()) && cc.getTargetType().equals(ReservedTypes.ANY.toString())) {
688                                 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.MANY);
689                         } else if (cc.getSourceType().equals("a") && cc.getTargetType().equals(ReservedTypes.ANY.toString())) {
690                                 assertTrue(cc.getMultiplicity() == ChampConnectionMultiplicity.ONE);
691                         } else {
692                                 throw new AssertionError("Found unspecified connection constraint " + cc);
693                         }
694                 }       
695         }
696
697         @Test
698         public void testJacksonObjectMapping() {
699                 final ChampSchema schema = ChampSchema.create()
700                                                                                                 .withObjectConstraint()
701                                                                                                         .onType("a")
702                                                                                                         .withPropertyConstraint()
703                                                                                                                 .onField("z")
704                                                                                                                 .ofType(ChampField.Type.STRING)
705                                                                                                                 .optional()
706                                                                                                                 .build()
707                                                                                                         .build()
708                                                                                                 .withObjectConstraint()
709                                                                                                         .onType("b")
710                                                                                                         .withPropertyConstraint()
711                                                                                                                 .onField("y")
712                                                                                                                 .ofType(ChampField.Type.LONG)
713                                                                                                                 .required()
714                                                                                                                 .build()
715                                                                                                         .build()
716                                                                                                 .withRelationshipConstraint()
717                                                                                                         .onType("one")
718                                                                                                         .withPropertyConstraint()
719                                                                                                                 .onField("nine")
720                                                                                                                 .ofType(ChampField.Type.INTEGER)
721                                                                                                                 .optional()
722                                                                                                                 .build()
723                                                                                                         .withConnectionConstraint()
724                                                                                                                 .sourcedFrom("a")
725                                                                                                                 .targetedTo("b")
726                                                                                                                 .withMultiplicity(ChampConnectionMultiplicity.NONE)
727                                                                                                                 .build()
728                                                                                                         .withConnectionConstraint()
729                                                                                                                 .sourcedFrom("a")
730                                                                                                                 .targetedToAny()
731                                                                                                                 .withMultiplicity(ChampConnectionMultiplicity.ONE)
732                                                                                                                 .build()
733                                                                                                         .withConnectionConstraint()
734                                                                                                                 .sourcedFromAny()
735                                                                                                                 .targetedTo("b")
736                                                                                                                 .withMultiplicity(ChampConnectionMultiplicity.MANY)
737                                                                                                                 .build()
738                                                                                                         .withConnectionConstraint()
739                                                                                                                 .sourcedFromAny()
740                                                                                                                 .targetedToAny()
741                                                                                                                 .withMultiplicity(ChampConnectionMultiplicity.MANY)
742                                                                                                                 .build()
743                                                                                                         .build()
744                                                                                                 .build();
745
746                 final ObjectMapper om = new ObjectMapper();
747
748                 try {
749                         final byte[] serialized = om.writeValueAsBytes(schema);
750                         System.out.println(new String(serialized, "UTF-8"));
751                         final ChampSchema deserialized = om.readValue(serialized, ChampSchema.class);
752                         assert schema.equals(deserialized);
753                 } catch (IOException e) {
754                         throw new AssertionError(e);
755                 }
756
757         }
758 }