package com.temenos.interaction.example.odata.notes; /* * #%L * interaction-example-odata-notes * %% * Copyright (C) 2012 - 2013 Temenos Holdings N.V. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import com.temenos.interaction.commands.odata.ODataUriSpecification; import com.temenos.interaction.core.hypermedia.Action; import com.temenos.interaction.core.hypermedia.CollectionResourceState; import com.temenos.interaction.core.hypermedia.ResourceState; import com.temenos.interaction.core.hypermedia.ResourceStateMachine; import com.temenos.interaction.core.hypermedia.Transition; public class Behaviour { // entities private final static String NOTE = "Note"; private final static String PERSON = "Person"; private final static String PERSONS_PATH = "/Persons"; private final static String PERSON_ITEM_PATH = "/Persons({id})"; private final static String NOTES_PATH = "/Notes"; private final static String NOTE_PERSON_PATH = "/Notes({id})/NotePerson"; private final static String PERSON_NOTES_PATH = "/Persons({id})/PersonNotes"; public ResourceState getSimpleODataInteractionModel() { // the service root ResourceState initialState = new ResourceState("ServiceDocument", "ServiceDocument", createActionList(new Action("GETServiceDocument", Action.TYPE.VIEW), null), "/"); // notes service ResourceStateMachine notes = getNotesSM(); initialState.addTransition("GET", notes); // persons service ResourceStateMachine persons = getPersonsSM(); initialState.addTransition("GET", persons); // now link the two entity sets addTransitionsBetweenRSMs(new ResourceStateMachine(initialState)); return initialState; } public void addTransitionsBetweenRSMs(ResourceStateMachine root) { Map<String, String> uriLinkageMap = new HashMap<String, String>(); // links to entities of the same type, therefore same id linkage uriLinkageMap.clear(); // link NotePerson to PersonNotes root.getResourceStateByName("NotePerson").addTransition(new Transition.Builder().method("GET").target(root.getResourceStateByName("PersonNotes")).uriParameters(uriLinkageMap).build()); // link PersonNotes NotePerson ((CollectionResourceState) root.getResourceStateByName("PersonNotes")).addTransition(new Transition.Builder().flags(Transition.FOR_EACH).method("GET").target(root.getResourceStateByName("NotePerson")).uriParameters(uriLinkageMap).build()); // link back to person root.getResourceStateByName("NotePerson").addTransition(new Transition.Builder().method("GET").target(root.getResourceStateByName("person")).uriParameters(uriLinkageMap).build()); // link back to note ((CollectionResourceState) root.getResourceStateByName("PersonNotes")).addTransition(new Transition.Builder().flags(Transition.FOR_EACH).method("GET").target(root.getResourceStateByName("note")).uriParameters(uriLinkageMap).build()); // Links from a note to a person uriLinkageMap.clear(); uriLinkageMap.put("id", "{personId}"); // link from each person's notes back to person ((CollectionResourceState) root.getResourceStateByName("PersonNotes")).addTransition(new Transition.Builder().flags(Transition.FOR_EACH).method("GET").target(root.getResourceStateByName("person")).uriParameters(uriLinkageMap).build()); // link from each note to their person ((CollectionResourceState) root.getResourceStateByName("Notes")).addTransition(new Transition.Builder().flags(Transition.FOR_EACH).method("GET").target(root.getResourceStateByName("person")).uriParameters(uriLinkageMap).build()); uriLinkageMap.clear(); } public ResourceState getNotes() { CollectionResourceState notes = new CollectionResourceState(NOTE, "Notes", createActionList(new Action("GETEntities", Action.TYPE.VIEW), null), NOTES_PATH); ResourceState pseudoCreated = new ResourceState(notes, "Note.PseudoCreated", createActionList(null, new Action("CreateEntity", Action.TYPE.ENTRY))); // Option 1 for configuring the interaction - use another state as a parent ResourceState note = new ResourceState(notes, "note", createActionList(new Action("GETEntity", Action.TYPE.VIEW), null), "({id})"); ResourceState noteUpdated = new ResourceState(note, "updated", createActionList(null, new Action("UpdateEntity", Action.TYPE.ENTRY)), null, "edit".split(" ") ); ResourceState noteDeleted = new ResourceState(note, "deleted", createActionList(null, new Action("DeleteEntity", Action.TYPE.ENTRY)), null, "edit".split(" ") ); /* * this navigation property demonstrates an Action properties and * uri specification to get conceptual configuration into a Command */ Properties personNotesNavProperties = new Properties(); personNotesNavProperties.put("entity", NOTE); personNotesNavProperties.put("navproperty", "NotePerson"); /* * The link relation for a NavProperty must match the NavProperty name to keep ODataExplorer happy */ ResourceState notePerson = new ResourceState(PERSON, "NotePerson", createActionList(new Action("GETNavProperty", Action.TYPE.VIEW, personNotesNavProperties), null), NOTE_PERSON_PATH, new ODataUriSpecification().getTemplate(NOTES_PATH, ODataUriSpecification.NAVPROPERTY_URI_TYPE)); // use to add collection transition to individual items Map<String, String> uriLinkageMap = new HashMap<String, String>(); uriLinkageMap.put("id", "{id}"); // edit notes.addTransition(new Transition.Builder().flags(Transition.FOR_EACH).method("PUT").target(noteUpdated).uriParameters(uriLinkageMap).build()); notes.addTransition(new Transition.Builder().flags(Transition.FOR_EACH).method("GET").target(note).uriParameters(uriLinkageMap).build()); notes.addTransition(new Transition.Builder().flags(Transition.FOR_EACH).method("GET").target(notePerson).uriParameters(uriLinkageMap).build()); notes.addTransition(new Transition.Builder().method("POST").target(pseudoCreated).build()); // auto transition to new note that was just created pseudoCreated.addTransition(new Transition.Builder().flags(Transition.AUTO).target(note).build()); note.addTransition(new Transition.Builder().method("GET").target(notePerson).uriParameters(uriLinkageMap).build()); note.addTransition(new Transition.Builder().method("PUT").target(noteUpdated).build()); note.addTransition(new Transition.Builder().method("DELETE").target(noteDeleted).build()); return notes; } public ResourceStateMachine getNotesSM() { return new ResourceStateMachine(getNotes()); } public ResourceState getPersons() { CollectionResourceState persons = new CollectionResourceState(PERSON, "Persons", createActionList(new Action("GETEntities", Action.TYPE.VIEW), null), PERSONS_PATH); ResourceState pseudo = new ResourceState(persons, "Person.PseudoCreated", createActionList(null, new Action("CreateEntity", Action.TYPE.ENTRY))); // Option 2 for configuring the interaction - specify the entity, state, and fully qualified path ResourceState person = new ResourceState(PERSON, "person", createActionList(new Action("GETEntity", Action.TYPE.VIEW), null), PERSON_ITEM_PATH); /* * this navigation property demostrates an Action properties and * uri specification to get conceptual configuration into a Command */ Properties personNotesNavProperties = new Properties(); personNotesNavProperties.put("entity", PERSON); personNotesNavProperties.put("navproperty", "PersonNotes"); /* * The link relation for a NavProperty must match the NavProperty name to keep ODataExplorer happy */ CollectionResourceState personNotes = new CollectionResourceState(NOTE, "PersonNotes", createActionList(new Action("GETNavProperty", Action.TYPE.VIEW, personNotesNavProperties), null), PERSON_NOTES_PATH, new ODataUriSpecification().getTemplate(PERSONS_PATH, ODataUriSpecification.NAVPROPERTY_URI_TYPE)); // add collection transition to individual items Map<String, String> uriLinkageMap = new HashMap<String, String>(); uriLinkageMap.put("id", "{id}"); persons.addTransition(new Transition.Builder().flags(Transition.FOR_EACH).method("GET").target(person).uriParameters(uriLinkageMap).build()); persons.addTransition(new Transition.Builder().flags(Transition.FOR_EACH).method("GET").target(personNotes).uriParameters(uriLinkageMap).build()); persons.addTransition(new Transition.Builder().method("POST").target(pseudo).build()); // add auto transition to new person that was just created pseudo.addTransition(new Transition.Builder().flags(Transition.AUTO).target(person).build()); person.addTransition(new Transition.Builder().method("GET").target(personNotes).uriParameters(uriLinkageMap).build()); return persons; } public ResourceStateMachine getPersonsSM() { return new ResourceStateMachine(getPersons()); } private List<Action> createActionList(Action view, Action entry) { List<Action> actions = new ArrayList<Action>(); if (view != null) actions.add(view); if (entry != null) actions.add(entry); return actions; } }