Skip to content

Commit

Permalink
compressed relationship representation in input and by default in out…
Browse files Browse the repository at this point in the history
…put, bumped to 1.5.1 for release
  • Loading branch information
eviltester committed Jul 6, 2020
1 parent c3fa83d commit c286cfa
Show file tree
Hide file tree
Showing 22 changed files with 291 additions and 126 deletions.
58 changes: 55 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
<version>1.0.0</version>
<packaging>pom</packaging>


<properties>
<thingifier.version>1.5.1-SNAPSHOT</thingifier.version>
<thingifier.version>1.5.1</thingifier.version>
<java.version>1.8</java.version>
<!--<java.version>13</java.version>-->
</properties>

<modules>
Expand All @@ -19,4 +19,56 @@
<module>standAloneTodoListRestApi</module>
<module>standAloneTodoListManagerRestApi</module>
</modules>
</project>
</project>

<!--
1.5.1
- added simple view gui /gui
- added compressed relationships - as default in response
- both forms acceptable in the input
e.g.
~~~~~~~~
"task-of": [
{
"guid": "91b56544-3345-48e6-93f3-986e53586390"
}
],
"categories": [
{
"guid": "61693e4a-b1da-4adb-af37-d53d1b045311"
}
]
~~~~~~~~
instead of
~~~~~~~~
"relationships": [
{
"task-of": [
{
"projects": [
{
"guid": "91b56544-3345-48e6-93f3-986e53586390"
}
]
}
]
},
{
"categories": [
{
"categories": [
{
"guid": "61693e4a-b1da-4adb-af37-d53d1b045311"
}
]
}
]
}
]
~~~~~~~~
-->
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package uk.co.compendiumdev.todolist.application;

import spark.Spark;
import uk.co.compendiumdev.thingifier.Thingifier;
import uk.co.compendiumdev.thingifier.application.DefaultGUI;
import uk.co.compendiumdev.thingifier.application.ThingifierRestServer;
import uk.co.compendiumdev.thingifier.application.examples.TodoManagerThingifier;

Expand Down Expand Up @@ -52,9 +54,15 @@ public static void main(String[] args) {
return "";
});

Thingifier thingifier;

thingifier = new TodoManagerThingifier().get();

new DefaultGUI(thingifier).setupDefaultGUI();

ThingifierRestServer restServer;
restServer = new ThingifierRestServer(
args, "", new TodoManagerThingifier().get());

restServer = new ThingifierRestServer(args, "", thingifier);

System.out.println("Running on " + Spark.port());
System.out.println(" e.g. http://localhost:" + Spark.port());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package uk.co.compendiumdev.todolist.application;

import spark.Spark;
import uk.co.compendiumdev.thingifier.Thingifier;
import uk.co.compendiumdev.thingifier.application.DefaultGUI;
import uk.co.compendiumdev.thingifier.application.ThingifierRestServer;
import uk.co.compendiumdev.thingifier.application.examples.TodoListThingifier;

Expand Down Expand Up @@ -52,9 +54,15 @@ public static void main(String[] args) {
return "";
});

Thingifier thingifier;

thingifier = new TodoListThingifier().get();

new DefaultGUI(thingifier).setupDefaultGUI();

ThingifierRestServer restServer;
restServer = new ThingifierRestServer(
args, "", new TodoListThingifier().get());

restServer = new ThingifierRestServer(args, "", thingifier);

System.out.println("Running on " + Spark.port());
System.out.println(" e.g. http://localhost:" + Spark.port());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ private void parseMap() {
}

// because we are using crude XML and JSON parsing
// <project><title>My posted todo on the project</title></project>
// would become {"project":{"title":"My posted todo on the project"}}
// when we want {"title":"My posted todo on the project"}
// <project><title>My posted to do on the project</title></project>
// would become {"project":{"title":"My posted to do on the project"}}
// when we want {"title":"My posted to do on the project"}
// this is just a quick hack to amend it to support XML
// TODO: try to change this in the future to make it more robust, perhaps the API shouldn't take a String as the body, it should take a parsed class?
// TODO: BUG - since we remove the wrapper we might send in a POST <project><title>My posted todo on the project</title></project> to /todo and it will work fine if the fields are the same
// TODO: BUG - since we remove the wrapper we might send in a POST <project><title>My posted to do on the project</title></project> to /todo and it will work fine if the fields are the same
if (request.getHeader("Content-Type") != null && request.getHeader("Content-Type").endsWith("/xml")) {

// PROTOTYPE XML Conversion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,48 +35,129 @@ public ValidationReport validate(final BodyParser bodyargs, final ThingDefinitio
//is it a relationship?
String complexKey = complexKeyValue.getKey();
if(complexKey.startsWith("relationships.")){
String[] parts = complexKey.split("\\.");
if(parts.length!=4){
// invalid relationship
validRelationships = false;
report.addErrorMessage(String.format("%s is not a valid relationship",complexKey));
continue;
}
// is it a valid relationship name for this thing
if(!thingDefinition.hasRelationship(parts[1])){
validRelationships = false;
report.addErrorMessage(
String.format("%s is not a valid relationship for %s",
parts[1], thingDefinition.getName()));
continue;
}
// is it a valid relationship to the other thing
boolean foundRelationship=false;
for(RelationshipVector relationships : thingDefinition.getRelationships(parts[1])){
if(relationships.getTo().definition().getPlural().equals(parts[2])){
foundRelationship=true;
}
}
if(!foundRelationship){
if(!validateComplexFourPartRelationshipDefinition(thingDefinition, report, complexKey, complexKeyValue.getValue())){
validRelationships=false;
report.addErrorMessage(
String.format("%s to %s is not a valid relationship for %s",
parts[1], parts[2], thingDefinition.getName()));
continue;
}
// check that the thing we want to relate with exists
String guid = complexKeyValue.getValue();
final ThingInstance thingToRelateTo = thingifier.
getThingNamedSingularOrPlural(parts[2]).findInstanceByGUID(guid);
if(thingToRelateTo==null){
validRelationships=false;
report.addErrorMessage(
String.format("cannot find %s of %s to relate to with guid %s",
parts[3], parts[2], guid));
};
}else{
if(complexKey.contains(".")){
// it might be a relationship
String[] parts = complexKey.split("\\.");
if(thingDefinition.hasRelationship(parts[0])) {
validRelationships = validateCompressedRelationshipDefinition(thingDefinition, report, complexKey, complexKeyValue.getValue());
}
}
}
}

report.setValid(validRelationships);
return report;
}

private boolean validateCompressedRelationshipDefinition(
final ThingDefinition thingDefinition, final ValidationReport report,
final String complexKey, final String complexKeyValue) {

boolean validRelationships=true;
String[] parts = complexKey.split("\\.");

if(parts.length!=2){
// invalid relationship
validRelationships = false;
report.addErrorMessage(String.format("%s is not a valid relationship",complexKey));
return validRelationships;
}
String relationShipName = parts[0];
String fieldToMatchForGuid = parts[1];
String guidValue = complexKeyValue;

// is it a valid relationship name for this thing
if(!thingDefinition.hasRelationship(relationShipName)){
validRelationships = false;
report.addErrorMessage(
String.format("%s is not a valid relationship for %s",
relationShipName, thingDefinition.getName()));
return validRelationships;
}

// find the other thing
if(!fieldToMatchForGuid.equals("guid")){
validRelationships = false;
report.addErrorMessage(String.format(
"Only support relationship references for guid, not for %s", fieldToMatchForGuid));
return validRelationships;
}

final ThingInstance thingToRelateTo = thingifier.findThingInstanceByGuid(guidValue);
if(thingToRelateTo==null){
validRelationships=false;
report.addErrorMessage(
String.format("cannot find %s to relate to with guid %s",
relationShipName, guidValue));
return validRelationships;
}

// is it a valid relationship to the other thing
boolean foundRelationship=false;
for(RelationshipVector relationships : thingDefinition.getRelationships(relationShipName)){
if(relationships.getTo().definition().getPlural().equals(
thingToRelateTo.getEntity().getPlural())){
foundRelationship=true;
}
}
if(!foundRelationship){
validRelationships=false;
report.addErrorMessage(
String.format("%s to %s is not a valid relationship for %s",
relationShipName, thingToRelateTo.getEntity().getName(), thingDefinition.getName()));
return validRelationships;
}
// check that the thing we want to relate with exists
return validRelationships;
}

private boolean validateComplexFourPartRelationshipDefinition(
final ThingDefinition thingDefinition, final ValidationReport report,
final String complexKey, final String complexKeyValue) {
String[] parts = complexKey.split("\\.");
Boolean validRelationships = true;
if(parts.length!=4){
// invalid relationship
validRelationships = false;
report.addErrorMessage(String.format("%s is not a valid relationship",complexKey));
return validRelationships;
}
// is it a valid relationship name for this thing
if(!thingDefinition.hasRelationship(parts[1])){
validRelationships = false;
report.addErrorMessage(
String.format("%s is not a valid relationship for %s",
parts[1], thingDefinition.getName()));
return validRelationships;
}
// is it a valid relationship to the other thing
boolean foundRelationship=false;
for(RelationshipVector relationships : thingDefinition.getRelationships(parts[1])){
if(relationships.getTo().definition().getPlural().equals(parts[2])){
foundRelationship=true;
}
}
if(!foundRelationship){
validRelationships=false;
report.addErrorMessage(
String.format("%s to %s is not a valid relationship for %s",
parts[1], parts[2], thingDefinition.getName()));
return validRelationships;
}
// check that the thing we want to relate with exists
String guid = complexKeyValue;
final ThingInstance thingToRelateTo = thingifier.
getThingNamedSingularOrPlural(parts[2]).findInstanceByGUID(guid);
if(thingToRelateTo==null){
validRelationships=false;
report.addErrorMessage(
String.format("cannot find %s of %s to relate to with guid %s",
parts[3], parts[2], guid));
}
return validRelationships;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ private List<RelationshipDetails> getRelationshipsFromArgs(final BodyParser body
parts[1], parts[2], parts[3],
complexKeyValue.getValue()));
}
}else{
// support compressed relationships
if(complexKey.contains(".")) {
String[] parts = complexKey.split("\\.");
// assume it is a relationship - because of earlier validation
if(parts.length == 2){
final ThingInstance instanceToRelateTo = thingifier.findThingInstanceByGuid(complexKeyValue.getValue());
if(instanceToRelateTo!=null){
relationships.add(
new RelationshipDetails(
parts[0], instanceToRelateTo.getEntity().getPlural(), parts[1],
complexKeyValue.getValue()));
}
}
}
}
}
return relationships;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package uk.co.compendiumdev.thingifier.application;

import spark.Service;
import spark.Spark;
import uk.co.compendiumdev.thingifier.Thingifier;
import uk.co.compendiumdev.thingifier.application.examples.TodoListThingifier;
import uk.co.compendiumdev.thingifier.application.examples.TodoManagerThingifier;
import uk.co.compendiumdev.thingifier.reporting.RestApiDocumentationGenerator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static spark.Spark.get;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

public class ThingifierVersionDetails {

final public static String VERSION_NUMBER = "1.4";
final public static String VERSION_NUMBER = "1.5";

final public static String COPYRIGHT_YEAR = "2018";
final public static String COPYRIGHT_YEAR = "2020";
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
public class TodoListThingifier {

/*
A Very simple list of todo items
A Very simple list of to do items
*/
public Thingifier get() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ public String getDefault() {
}

// TODO add type for SET having a set of valid values
// TODO add type for EXPANDINGSET having a set of valid initial values, but allow user expansion
// TODO add type for ID having an incremental unique id per entity type
// TODO add type for CREATEDDATE - automatically maintain - possibly allow configuring format
// TODO add type for AMENDEDDATE - automatically maintain - possibly allow configuring format
Loading

0 comments on commit c286cfa

Please sign in to comment.