/**
   * The startRenderTask creates a new OSD of the object type render_task in the repository in the
   * specified folder. This task object is read by the render server and updated with status updates
   * by the render process (which are written to custom metadata
   * /meta/metaset=render_output/messages/). It is up to the client to interpret the messages. The
   * overall status of the render task can be determined by looking at the procstate attribute:<br>
   * While the task is waiting for the render server to pick it up, its procstate is set to
   * "waiting". While the task is running, its procstate is set to "running". After the task is
   * finished, the task's procstate attribute is set to "finished". If the task should fail, the
   * task's procstate is set to "failed".
   *
   * <h2>Required permissions</h2>
   *
   * CREATE_OBJECT
   *
   * @param cmd a Map of HTTP request parameters containing:<br>
   *     <ul>
   *       <li>command=startrendertask
   *       <li>[name]=optional name of the task, defaults to "RenderTask"
   *       <li>ticket=session ticket
   *       <li>parentid = id of the folder where the task-object will be created
   *       <li>metadata = xml to use as the metadata metaset=render_input field. It must contain at
   *           least the element
   *           <pre>{@code <renderTaskName>}</pre>
   *           which holds the name of the render task that will be performed. It should contain the
   *           sourceId element to specify the id of the source content object to be rendered.<br>
   *           Example for metadata content:<br>
   *           <pre>{@code
   * <metaset type="render_input"><sourceId>542</sourceId><renderTaskName>foo</renderTaskName></metaset>
   *
   * }</pre>
   *     </ul>
   *
   * @return a CinnamonException if the object cannot be instantiated for any reason, or a Response
   *     object with the following XML content:
   *     <pre>{@code
   *  <startRenderTask>
   *    <taskObjectId>123</taskObjectId>
   *    <success>success.startRenderTask</success>
   * </startRenderTask>
   * }</pre>
   */
  @CinnamonMethod(checkTrigger = "true")
  public Response startRenderTask(Map<String, Object> cmd) {
    // create object and validate permission
    User user = getUser();
    ObjectSystemData osd = new ObjectSystemData(cmd, user, false);
    (new Validator(user)).validateCreate(osd.getParent());

    String renderInput;
    if (cmd.containsKey("metadata")) {
      Node meta = ParamParser.parseXml((String) cmd.get("metadata"), "error.param.metadata");
      renderInput = meta.asXML();
    } else {
      renderInput = "";
    }
    String metasetStr =
        "<meta>" + renderInput + "<metaset type=\"render_output\"></metaset></meta>";
    Node metaset = ParamParser.parseXml(metasetStr, null);
    osd.setMetadata(metaset.asXML());
    LifeCycleDAO lcDao = daoFactory.getLifeCycleDAO(em);
    LifeCycle lc = lcDao.findByName(Constants.RENDER_SERVER_LIFECYCLE);
    if (lc == null) {
      throw new CinnamonConfigurationException(
          Constants.RENDER_SERVER_LIFECYCLE + " lifecycle was not found.");
    }
    if (lc.getDefaultState() == null) {
      throw new CinnamonConfigurationException(
          Constants.RENDER_SERVER_LIFECYCLE
              + " lifecycle is not configured correctly. Needs defaultState.");
    }
    osd.setState(lc.getDefaultState());
    osd.setProcstate(Constants.RENDERSERVER_RENDER_TASK_NEW);

    if (cmd.containsKey("name")) {
      osd.setName(((String) cmd.get("name")).trim());
    } else {
      osd.setName("RenderTask");
    }

    ObjectTypeDAO otDao = daoFactory.getObjectTypeDAO(em);
    ObjectType renderTaskType = otDao.findByName(Constants.OBJECT_TYPE_RENDER_TASK);
    if (renderTaskType == null) {
      throw new CinnamonConfigurationException("Could not find required render task object type.");
    }
    osd.setType(renderTaskType);
    ObjectSystemDataDAO oDao = daoFactory.getObjectSystemDataDAO(em);
    oDao.makePersistent(osd);

    // create response
    XmlResponse resp = new XmlResponse(res);
    Element root = resp.getDoc().addElement("startRenderTask");
    root.addElement("taskObjectId").addText(String.valueOf(osd.getId()));
    root.addElement("success").addText("success.startRenderTask");
    return resp;
  }
  public RelationType(Map<String, String> cmd) {
    name = cmd.get("name");
    description = cmd.get("description");
    leftobjectprotected = cmd.get("leftobjectprotected").equals("true");
    rightobjectprotected = cmd.get("rightobjectprotected").equals("true");
    cloneOnLeftCopy = cmd.get("cloneOnLeftCopy").equals("true");
    cloneOnRightCopy = cmd.get("cloneOnRightCopy").equals("true");
    cloneOnLeftVersion = cmd.get("cloneOnLeftVersion").equals("true");
    cloneOnRightVersion = cmd.get("cloneOnRightVersion").equals("true");

    EntityManager em = HibernateSession.getLocalEntityManager();
    RelationResolverDAO rdd = daoFactory.getRelationResolverDAO(em);
    /*
     * Design note: resolve by name is intended to make it easier for testing
     * as you can create a test relation type without having to look up the id of the
     * default (or to-be-tested) relation resolver.
     */
    if (cmd.containsKey("right_resolver")) {
      rightResolver = rdd.findByName(cmd.get("right_resolver"));
    } else if (cmd.containsKey("right_resolver_id")) {
      rightResolver =
          rdd.get(
              ParamParser.parseLong(cmd.get("right_resolver_id"), "error.param.right_resolver_id"));
    } else {
      rightResolver = rdd.findByName(Constants.RELATION_RESOLVER_FIXED);
    }
    if (cmd.containsKey("left_resolver")) {
      leftResolver = rdd.findByName(cmd.get("left_resolver"));
    } else if (cmd.containsKey("left_resolver_id")) {
      rightResolver =
          rdd.get(
              ParamParser.parseLong(cmd.get("left_resolver_id"), "error.param.left_resolver_id"));
    } else {
      leftResolver = rdd.findByName(Constants.RELATION_RESOLVER_FIXED);
    }

    if (rightResolver == null) {
      throw new CinnamonException("error.param.right_resolver_id");
    }
    if (leftResolver == null) {
      throw new CinnamonException("error.param.left_resolver_id");
    }

    log.debug("leftResolver: " + leftResolver);
    log.debug("rightResolver: " + rightResolver);
  }