/*
  * Add transition properties to entity info
  */
 public static void addNavPropertiesToEntityInfo(
     EntityInfo entityInfo, InteractionModel interactionModel) {
   IMResourceStateMachine rsm = interactionModel.findResourceStateMachine(entityInfo.getClazz());
   if (rsm != null) {
     for (IMTransition transition : rsm.getEntityStateTransitions()) {
       List<FieldInfo> properties = entityInfo.getAllFieldInfos();
       List<String> annotations = new ArrayList<String>();
       if (transition instanceof IMCollectionStateTransition) {
         // Transition to collection state
         // TODO fix reciprocal links
         // annotations.add("@OneToMany(cascade = CascadeType.ALL, mappedBy = \"" +
         // transition.getTargetStateName() + "\")");
         // properties.add(new FieldInfo(transition.getTargetStateName(), "Collection<" +
         // transition.getTargetEntityName() + ">", annotations));
       } else if (transition instanceof IMEntityStateTransition) {
         // Transition to entity state
         IMEntityStateTransition t = (IMEntityStateTransition) transition;
         annotations.add(
             "@JoinColumn(name = \""
                 + t.getLinkProperty()
                 + "\", referencedColumnName = \""
                 + t.getTargetResourceStateMachine().getMappedEntityProperty()
                 + "\", insertable = false, updatable = false)");
         annotations.add("@ManyToOne(optional = false)");
         properties.add(
             new FieldInfo(
                 t.getTargetState().getName(),
                 t.getTargetResourceStateMachine().getEntityName(),
                 annotations));
       }
     }
   }
 }
  @Test
  public void testGetRIM() {
    // Parse the test metadata
    MetadataParser parser = new MetadataParser();
    InputStream is =
        parser.getClass().getClassLoader().getResourceAsStream(METADATA_AIRLINE_XML_FILE);
    Metadata metadata = parser.parse(is);
    Assert.assertNotNull(metadata);

    // Define the interaction model
    InteractionModel interactionModel = new InteractionModel(metadata);

    IMResourceStateMachine rsmFlightSchedule =
        interactionModel.findResourceStateMachine("FlightSchedule");
    IMResourceStateMachine rsmAirport = interactionModel.findResourceStateMachine("Airport");
    IMResourceStateMachine rsmFlight = interactionModel.findResourceStateMachine("Flight");
    IMResourceStateMachine rsmPassenger = interactionModel.findResourceStateMachine("Passenger");
    rsmFlight.addTransitionToEntityState(
        "flight", rsmFlightSchedule, "flightschedule", "flightScheduleNum", null);
    rsmFlightSchedule.addTransitionToEntityState(
        "flightschedule", rsmAirport, "departureAirport", "departureAirportCode", null);
    rsmFlightSchedule.addTransitionToEntityState(
        "flightschedule", rsmAirport, "arrivalAirport", "arrivalAirportCode", null);
    rsmAirport.addTransitionToCollectionState(
        "airport",
        rsmFlightSchedule,
        "departures",
        "departureAirportCode eq '{code}'",
        "departureAirportCode",
        null);
    rsmAirport.addTransitionToCollectionState(
        "airport",
        rsmFlightSchedule,
        "arrivals",
        "arrivalAirportCode eq '{code}'",
        "arrivalAirportCode",
        null);
    rsmPassenger.addTransitionToEntityState("passenger", rsmFlight, "flight", "flightID", null);

    // Run the generator
    JPAResponderGen generator = new JPAResponderGen(true);
    Commands commands = JPAResponderGen.getDefaultCommands();
    String rimDSL = null;
    try {
      InputStream isRimDsl = generator.getRIM(interactionModel, commands);
      assertNotNull(isRimDsl);

      rimDSL = CharStreams.toString(new InputStreamReader(isRimDsl, "UTF-8"));
    } catch (Exception age) {
      fail(age.getMessage());
    }

    // Check the rim dsl
    assertTrue(rimDSL.contains("initial resource ServiceDocument"));
    assertTrue(rimDSL.contains("GET -> FlightSchedules"));
    assertTrue(rimDSL.contains("resource FlightSchedules"));
    assertTrue(
        rimDSL.contains(
            "GET *-> flightschedule {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{flightScheduleID}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(
        rimDSL.contains(
            "GET *-> flightschedule_departureAirport {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{flightScheduleID}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(rimDSL.contains("resource flightschedule_departureAirport"));
    assertTrue(rimDSL.contains("path: \"/FlightSchedules({id})/departureAirport\""));
    assertTrue(rimDSL.contains("GET -> Passengers"));
    assertTrue(rimDSL.contains("resource Passengers"));
  }
  @Test
  public void testRIMWithoutReciprocalLinks() {
    // Parse the test metadata
    MetadataParser parser = new MetadataParser();
    InputStream is =
        parser.getClass().getClassLoader().getResourceAsStream(METADATA_AIRLINE_XML_FILE);
    Metadata metadata = parser.parse(is);
    Assert.assertNotNull(metadata);

    // Define the interaction model
    InteractionModel interactionModel = new InteractionModel(metadata);

    // Do not specify a reciprocal link
    IMResourceStateMachine rsmFlightSchedule =
        interactionModel.findResourceStateMachine("FlightSchedule");
    IMResourceStateMachine rsmAirport = interactionModel.findResourceStateMachine("Airport");
    IMResourceStateMachine rsmFlight = interactionModel.findResourceStateMachine("Flight");
    IMResourceStateMachine rsmPassenger = interactionModel.findResourceStateMachine("Passenger");
    rsmFlight.addTransitionToEntityState(
        "flight", rsmFlightSchedule, "flightschedule", "flightScheduleNum", null);
    rsmFlightSchedule.addTransitionToEntityState(
        "flightschedule", rsmAirport, "departureAirport", "departureAirportCode", null);
    rsmFlightSchedule.addTransitionToEntityState(
        "flightschedule", rsmAirport, "arrivalAirport", "arrivalAirportCode", null);
    rsmAirport.addTransitionToCollectionState(
        "airport",
        rsmFlightSchedule,
        "departures",
        "departureAirportCode eq '{code}'",
        "departureAirportCode",
        "departures");
    rsmAirport.addTransitionToCollectionState(
        "airport",
        rsmFlightSchedule,
        "arrivals",
        "arrivalAirportCode eq '{code}'",
        "arrivalAirportCode",
        "arrivals");
    rsmPassenger.addTransitionToEntityState("passenger", rsmFlight, "flight", "flightID", "flight");

    // Run the generator
    MockGenerator generator = new MockGenerator();
    boolean status =
        generator.generateArtifacts(
            metadata,
            interactionModel,
            new File("target/FlightResponder/classes"),
            new File("target/FlightResponder/classes"),
            true);

    // Check results
    assertTrue(status);

    // Test rim dsl
    assertTrue(
        generator.generatedRimDsl.contains(
            "GET *-> flightschedule_departureAirport {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{flightScheduleID}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(
        generator.generatedRimDsl.contains(
            "GET -> flightschedule_departureAirport {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{flightScheduleID}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(
        generator.generatedRimDsl.contains(
            "GET *-> flightschedule_arrivalAirport {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{flightScheduleID}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(
        generator.generatedRimDsl.contains(
            "GET -> flightschedule_arrivalAirport {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{flightScheduleID}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(
        generator.generatedRimDsl.contains(
            "GET -> airport_arrivals {"
                + RIM_LINE_SEP
                + "\t\ttitle: \"arrivals\""
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{code}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(
        generator.generatedRimDsl.contains(
            "GET -> airport_departures {"
                + RIM_LINE_SEP
                + "\t\ttitle: \"departures\""
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{code}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(
        generator.generatedRimDsl.contains(
            "GET -> passenger_flight {"
                + RIM_LINE_SEP
                + "\t\ttitle: \"flight\""
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{passengerNo}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
  }
  /*
   * To support resource state transitions (as opposed to application state transitions)
   * we use a pseudo state in our resource interaction model.  A pseudo state does not necessarily
   * have an addressable uri, and always has actions.
   */
  @Test
  public void testIMWithResourcePseudoStates() {
    // Parse the test metadata
    MetadataParser parser = new MetadataParser();
    InputStream is =
        parser.getClass().getClassLoader().getResourceAsStream(METADATA_AIRLINE_XML_FILE);
    Metadata metadata = parser.parse(is);
    Assert.assertNotNull(metadata);

    // Define the interaction model
    InteractionModel interactionModel = new InteractionModel(metadata);

    // Add CRUD pseudo states to an entity/entityset
    IMResourceStateMachine rsmAirport = interactionModel.findResourceStateMachine("Airport");
    rsmAirport.addPseudoStateTransition(
        "Airports", "created", "Airports", "POST", null, "CreateEntity", null, true);
    rsmAirport.addPseudoStateTransition(
        "airport", "updated", "airport", "PUT", null, "UpdateEntity", "edit", false);
    rsmAirport.addPseudoStateTransition(
        "airport", "deleted", "DELETE", null, "DeleteEntity", "edit", false);

    // Run the generator
    MockGenerator generator = new MockGenerator();
    boolean status =
        generator.generateArtifacts(
            metadata,
            interactionModel,
            new File("target/FlightResponder/classes"),
            new File("target/FlightResponder/classes"),
            true);

    // Check results
    assertTrue(status);

    // Test rim dsl
    assertTrue(generator.generatedRimDsl.contains("POST -> Airports_created"));
    assertTrue(generator.generatedRimDsl.contains("PUT *-> airport_updated"));
    assertTrue(generator.generatedRimDsl.contains("PUT -> airport_updated"));
    assertTrue(generator.generatedRimDsl.contains("DELETE *-> airport_deleted"));
    assertTrue(generator.generatedRimDsl.contains("DELETE -> airport_deleted"));
    assertTrue(generator.generatedRimDsl.contains("resource Airports_created"));
    assertTrue(
        generator.generatedRimDsl.contains(
            "resource Airports_created {"
                + RIM_LINE_SEP
                + "\ttype: item"
                + RIM_LINE_SEP
                + "\tentity: Airport"
                + RIM_LINE_SEP
                + "\tactions [ CreateEntity ]"
                + RIM_LINE_SEP
                + "\tpath: \"/Airports()\""));

    assertTrue(
        generator.generatedRimDsl.contains(
            "resource airport_updated {"
                + RIM_LINE_SEP
                + "\ttype: item"
                + RIM_LINE_SEP
                + "\tentity: Airport"
                + RIM_LINE_SEP
                + "\tactions [ UpdateEntity ]"
                + RIM_LINE_SEP
                + "\trelations [ \"edit\" ]"
                + RIM_LINE_SEP
                + "\tpath: \"/Airports('{id}')\""));
    assertTrue(
        generator.generatedRimDsl.contains(
            "resource airport_deleted {"
                + RIM_LINE_SEP
                + "\ttype: item"
                + RIM_LINE_SEP
                + "\tentity: Airport"
                + RIM_LINE_SEP
                + "\tactions [ DeleteEntity ]"
                + RIM_LINE_SEP
                + "\trelations [ \"edit\" ]"
                + RIM_LINE_SEP
                + "\tpath: \"/Airports('{id}')/deleted\""));
    assertTrue(
        generator.generatedRimDsl.contains(
            "resource airport {"
                + RIM_LINE_SEP
                + "\ttype: item"
                + RIM_LINE_SEP
                + "\tentity: Airport"
                + RIM_LINE_SEP
                + "\tview: GETEntity"
                + RIM_LINE_SEP
                + "\tpath: \"/Airports('{id}')\""
                + RIM_LINE_SEP
                + "\tPUT -> airport_updated {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{code}\" ]"
                + RIM_LINE_SEP
                + "\t}"
                + RIM_LINE_SEP
                + "\tDELETE -> airport_deleted {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{code}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
  }
  @Test
  public void testGeneratedArtifactsFromConceptualModels() {
    // Parse the test metadata
    MetadataParser parser = new MetadataParser();
    InputStream is =
        parser.getClass().getClassLoader().getResourceAsStream(METADATA_AIRLINE_XML_FILE);
    Metadata metadata = parser.parse(is);
    Assert.assertNotNull(metadata);

    // Define the interaction model
    InteractionModel interactionModel = new InteractionModel(metadata);

    IMResourceStateMachine rsmFlightSchedule =
        interactionModel.findResourceStateMachine("FlightSchedule");
    IMResourceStateMachine rsmAirport = interactionModel.findResourceStateMachine("Airport");
    IMResourceStateMachine rsmFlight = interactionModel.findResourceStateMachine("Flight");
    IMResourceStateMachine rsmPassenger = interactionModel.findResourceStateMachine("Passenger");
    rsmFlight.addTransitionToEntityState(
        "flight", rsmFlightSchedule, "flightschedule", "flightScheduleNum", null);
    rsmFlightSchedule.addTransitionToEntityState(
        "flightschedule", rsmAirport, "departureAirport", "departureAirportCode", null);
    rsmFlightSchedule.addTransitionToEntityState(
        "flightschedule", rsmAirport, "arrivalAirport", "arrivalAirportCode", null);
    rsmAirport.addTransitionToCollectionState(
        "airport",
        rsmFlightSchedule,
        "departures",
        "departureAirportCode eq '{code}'",
        "departureAirportCode",
        null);
    rsmAirport.addTransitionToCollectionState(
        "airport",
        rsmFlightSchedule,
        "arrivals",
        "arrivalAirportCode eq '{code}'",
        "arrivalAirportCode",
        null);
    rsmPassenger.addTransitionToEntityState("passenger", rsmFlight, "flight", "flightID", null);

    // Run the generator
    MockGenerator generator = new MockGenerator();
    boolean status =
        generator.generateArtifacts(
            metadata,
            interactionModel,
            new File("target/FlightResponder/classes"),
            new File("target/FlightResponder/classes"),
            true);

    // Check results
    assertTrue(status);

    assertTrue(generator.generatedClasses.size() == 4);
    assertTrue(generator.generatedClasses.get(0).contains("public class Flight"));
    assertTrue(generator.generatedClasses.get(1).contains("public class Airport"));
    assertTrue(generator.generatedClasses.get(2).contains("public class FlightSchedule"));
    assertTrue(generator.generatedClasses.get(3).contains("public class Passenger"));

    assertTrue(generator.generateResponderDML.contains("INSERT INTO `Flight`("));
    assertTrue(generator.generateResponderDML.contains("INSERT INTO `Airport`("));
    assertTrue(generator.generateResponderDML.contains("INSERT INTO `FlightSchedule`("));
    assertTrue(generator.generateResponderDML.contains("INSERT INTO `Passenger`("));

    assertTrue(
        generator.generatedPersistenceXML.contains("<class>FlightResponderModel.Flight</class>"));
    assertTrue(
        generator.generatedPersistenceXML.contains("<class>FlightResponderModel.Airport</class>"));
    assertTrue(
        generator.generatedPersistenceXML.contains(
            "<class>FlightResponderModel.FlightSchedule</class>"));
    assertTrue(
        generator.generatedPersistenceXML.contains(
            "<class>FlightResponderModel.Passenger</class>"));

    assertTrue(
        generator.generatedSpringXML.contains(
            "<bean id=\"behaviour\" class=\"FlightResponderModel.FlightResponderBehaviour\" />"));

    assertTrue(
        generator.generatedSpringResourceManagerXML.contains(
            "<constructor-arg name=\"namespace\" value=\"FlightResponder\" />"));

    // Test rim dsl
    assertTrue(generator.generatedRimDsl.contains("initial resource ServiceDocument"));
    assertTrue(generator.generatedRimDsl.contains("GET -> FlightSchedules"));
    assertTrue(generator.generatedRimDsl.contains("resource FlightSchedules"));
    assertTrue(
        generator.generatedRimDsl.contains(
            "GET *-> flightschedule {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{flightScheduleID}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(
        generator.generatedRimDsl.contains(
            "GET *-> flightschedule_departureAirport {"
                + RIM_LINE_SEP
                + "\t\tparameters [ id=\"{flightScheduleID}\" ]"
                + RIM_LINE_SEP
                + "\t}"));
    assertTrue(generator.generatedRimDsl.contains("resource flightschedule_departureAirport"));
    assertTrue(
        generator.generatedRimDsl.contains("path: \"/FlightSchedules({id})/departureAirport\""));
    assertTrue(generator.generatedRimDsl.contains("GET -> Passengers"));
    assertTrue(generator.generatedRimDsl.contains("resource Passengers"));
  }