/**
   * Display the details of an actor.
   *
   * @param id the actor id
   */
  @With(CheckActorExists.class)
  @SubjectPresent
  public Result view(Long id) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // construct the corresponding form data (for the custom attributes)
    ActorFormData actorFormData = new ActorFormData(actor);

    // tables of actor in the same org unit
    Table<ActorListView> actorFilledTable = null;
    if (actor.orgUnit != null) {
      List<Actor> actors = ActorDao.getActorActiveAsListByOrgUnit(actor.orgUnit.id);

      List<ActorListView> actorsListView = new ArrayList<ActorListView>();
      for (Actor a : actors) {
        actorsListView.add(new ActorListView(a));
      }

      Set<String> hideColumnsForEntry = new HashSet<String>();
      hideColumnsForEntry.add("orgUnit");
      hideColumnsForEntry.add("manager");

      actorFilledTable =
          this.getTableProvider()
              .get()
              .actor
              .templateTable
              .fill(actorsListView, hideColumnsForEntry);
    }

    // competencies
    List<CompetencyListView> competenciesListView = new ArrayList<CompetencyListView>();
    for (Competency competency : actor.competencies) {
      if (competency.isActive) {
        competenciesListView.add(new CompetencyListView(competency, actor));
      }
    }

    Set<String> hideColumnsForCompetency = new HashSet<String>();
    hideColumnsForCompetency.add("isActive");
    hideColumnsForCompetency.add("editActionLink");
    hideColumnsForCompetency.add("deleteActionLink");

    Table<CompetencyListView> competenciesFilledTable =
        this.getTableProvider()
            .get()
            .competency
            .templateTable
            .fill(competenciesListView, hideColumnsForCompetency);

    // check if there are active competencies
    boolean existCompetencies = ActorDao.getCompetencyActiveAsList().size() > 0 ? true : false;

    return ok(
        views.html.core.actor.actor_view.render(
            actor, actorFormData, actorFilledTable, competenciesFilledTable, existCompetencies));
  }
  /**
   * Form to select the competencies of the actor.
   *
   * @param id the actor id
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result editCompetencies(Long id) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // construct the form
    Form<ActorCompetenciesFormData> competenciesForm =
        competenciesFormTemplate.fill(new ActorCompetenciesFormData(actor));

    return ok(
        views.html.core.actor.competencies_edit.render(
            actor, ActorDao.getCompetencyActiveAsVH(), competenciesForm));
  }
  /** Save the capacity. */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result saveCapacity() {

    // bind the form
    Form<ActorCapacityFormData> boundForm = capacityFormTemplate.bindFromRequest();

    // get the actor
    Long id = Long.valueOf(boundForm.data().get("id"));
    Actor actor = ActorDao.getActorById(id);

    // get the year
    Integer year = Integer.valueOf(boundForm.data().get("year"));

    if (boundForm.hasErrors()) {
      return ok(views.html.core.actor.actor_capacity.render(actor, year, boundForm, true));
    }

    ActorCapacityFormData capacityFormData = boundForm.get();

    for (ActorCapacity capacity : capacityFormData.getFilledCapacities()) {
      capacity.save();
    }

    Utilities.sendSuccessFlashMessage(Msg.get("core.actor.capacity.save.successful"));

    return redirect(
        controllers.core.routes.ActorController.capacity(
            capacityFormData.id, capacityFormData.year));
  }
  /**
   * Display the active portfolio entries for which the actor is manager or direct stakeholder.
   *
   * @param id the actor id
   * @param page the current page
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_VIEW_DYNAMIC_PERMISSION)
  public Result listPortfolioEntries(Long id, Integer page) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    Pagination<PortfolioEntry> pagination =
        PortfolioEntryDao.getPEActiveAsPaginationByManagerOrDirectStakeholder(
            this.getPreferenceManagerPlugin(), id);
    pagination.setCurrentPage(page);

    List<PortfolioEntryListView> portfolioEntriesView = new ArrayList<PortfolioEntryListView>();
    for (PortfolioEntry portfolioEntry : pagination.getListOfObjects()) {
      portfolioEntriesView.add(
          new PortfolioEntryListView(
              portfolioEntry,
              StakeholderDao.getStakeholderAsListByActorAndPE(id, portfolioEntry.id)));
    }

    Table<PortfolioEntryListView> filledTable =
        this.getTableProvider()
            .get()
            .portfolioEntry
            .templateTable
            .fill(
                portfolioEntriesView,
                PortfolioEntryListView.getHideNonDefaultColumns(false, false));

    return ok(
        views.html.core.actor.actor_portfolio_entry_list.render(actor, filledTable, pagination));
  }
  /**
   * Form to edit an actor (available from the details of an actor).
   *
   * @param id the actor id
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result edit(Long id) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // construct the form
    Form<ActorFormData> actorForm = formTemplate.fill(new ActorFormData(actor));

    // add the custom attributes values
    this.getCustomAttributeManagerService().fillWithValues(actorForm, Actor.class, id);

    return ok(
        views.html.core.actor.actor_edit.render(
            actor, actorForm, ActorDao.getActorTypeActiveAsVH()));
  }
  /** Process the form to select the competencies of the actor. */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result processEditCompetencies() {

    // bind the form
    Form<ActorCompetenciesFormData> boundForm = competenciesFormTemplate.bindFromRequest();

    // get the actor
    Long id = Long.valueOf(boundForm.data().get("id"));
    Actor actor = ActorDao.getActorById(id);

    if (boundForm.hasErrors()) {
      return ok(
          views.html.core.actor.competencies_edit.render(
              actor, ActorDao.getCompetencyActiveAsVH(), boundForm));
    }

    ActorCompetenciesFormData competenciesFormData = boundForm.get();

    competenciesFormData.fill(actor);
    // actor.saveManyToManyAssociations("competencies");

    if (actor.competencies.size() == 0) {
      actor.defaultCompetency = null;
      actor.save();
    } else if (actor.competencies.size() == 1) {
      actor.defaultCompetency = actor.competencies.get(0);
      actor.save();
    } else {
      Form<ActorDefaultCompetencyFormData> defaultCompetencyForm =
          defaultCompetencyFormTemplate.fill(new ActorDefaultCompetencyFormData(actor));
      // force the default competency to an existing one
      actor.defaultCompetency = actor.competencies.get(0);
      actor.save();
      return ok(
          views.html.core.actor.default_competency_edit.render(
              actor,
              new DefaultSelectableValueHolderCollection<Long>(actor.competencies),
              defaultCompetencyForm));
    }

    Utilities.sendSuccessFlashMessage(Msg.get("core.actor.competencies.edit.successful"));

    return redirect(controllers.core.routes.ActorController.view(actor.id));
  }
  /** Process the form to create/edit an allocation with an activity. */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result processManageAllocatedActivity() {

    // bind the form
    Form<TimesheetActivityAllocatedActorFormData> boundForm =
        allocatedActivityFormTemplate.bindFromRequest();

    // get the actor
    Long id = Long.valueOf(boundForm.data().get("id"));
    Actor actor = ActorDao.getActorById(id);

    if (boundForm.hasErrors()
        || this.getCustomAttributeManagerService()
            .validateValues(boundForm, TimesheetActivityAllocatedActor.class)) {
      return ok(views.html.core.actor.allocated_activity_manage.render(actor, boundForm));
    }

    TimesheetActivityAllocatedActorFormData allocatedActivityFormData = boundForm.get();

    TimesheetActivityAllocatedActor allocatedActivity = null;

    if (allocatedActivityFormData.allocatedActivityId == null) { // create
      // case

      allocatedActivity = new TimesheetActivityAllocatedActor();
      allocatedActivityFormData.fill(allocatedActivity);
      allocatedActivity.save();

      Utilities.sendSuccessFlashMessage(Msg.get("core.actor.allocated_activity.add.successful"));

    } else { // edit case

      allocatedActivity =
          TimesheetDao.getTimesheetActivityAllocatedActorById(
              allocatedActivityFormData.allocatedActivityId);

      // security: the actor must be related to the object
      if (!allocatedActivity.actor.id.equals(id)) {
        return forbidden(views.html.error.access_forbidden.render(""));
      }

      allocatedActivityFormData.fill(allocatedActivity);
      allocatedActivity.update();

      Utilities.sendSuccessFlashMessage(Msg.get("core.actor.allocated_activity.edit.successful"));
    }

    // save the custom attributes
    this.getCustomAttributeManagerService()
        .validateAndSaveValues(
            boundForm, TimesheetActivityAllocatedActor.class, allocatedActivity.id);

    return redirect(controllers.core.routes.ActorController.allocationDetails(id, 0, 0, false));
  }
  /** Form to create a new actor (available from Admin menu). */
  @Restrict({@Group(IMafConstants.ACTOR_EDIT_ALL_PERMISSION)})
  public Result create() {

    // construct the form
    Form<ActorFormData> actorForm = formTemplate;

    // add the custom attributes default values
    this.getCustomAttributeManagerService().fillWithValues(actorForm, Actor.class, null);

    return ok(views.html.core.actor.actor_new.render(actorForm, ActorDao.getActorTypeActiveAsVH()));
  }
  /**
   * Display the details of a timesheet.
   *
   * @param id the actor id
   * @param stringDate a date in the format yyyy-MM-dd: the system gets the weekly report including
   *     this date, if empty it uses the current date.
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_VIEW_DYNAMIC_PERMISSION)
  public Result viewWeeklyTimesheet(Long id, String stringDate) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // get the report
    TimesheetReport report = TimesheetController.getTimesheetReport(stringDate, actor);

    return ok(
        views.html.core.actor.actor_view_weekly_timesheet.render(
            actor, report, timesheetReportApprovalFormTemplate));
  }
  /**
   * Delete an actor.
   *
   * @param id the actor id
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_DELETE_DYNAMIC_PERMISSION)
  public Result delete(Long id) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // delete the actor
    actor.doDelete();

    // success message
    Utilities.sendSuccessFlashMessage(Msg.get("core.actor.delete.successful"));

    return redirect(controllers.core.routes.SearchController.index());
  }
  /**
   * Display the capacity of the actor with management capability if enough perm.
   *
   * @param id the actor id
   * @param year the year (0 for the current)
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_VIEW_DYNAMIC_PERMISSION)
  public Result capacity(Long id, Integer year) {

    if (year.equals(0)) {
      year = Calendar.getInstance().get(Calendar.YEAR);
    }

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    Form<ActorCapacityFormData> capacityForm =
        capacityFormTemplate.fill(new ActorCapacityFormData(actor, year));

    // can edit
    boolean canEdit = getSecurityService().dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION, "");

    return ok(views.html.core.actor.actor_capacity.render(actor, year, capacityForm, canEdit));
  }
  /** Process the form to edit the default competency of an actor. */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result processEditDefaultCompetency() {

    // bind the form
    Form<ActorDefaultCompetencyFormData> boundForm =
        defaultCompetencyFormTemplate.bindFromRequest();

    // get the actor
    Long id = Long.valueOf(boundForm.data().get("id"));
    Actor actor = ActorDao.getActorById(id);

    ActorDefaultCompetencyFormData defaultCompetencyFormData = boundForm.get();

    defaultCompetencyFormData.fill(actor);
    actor.save();

    Utilities.sendSuccessFlashMessage(Msg.get("core.actor.competencies.edit.successful"));

    return redirect(controllers.core.routes.ActorController.view(actor.id));
  }
  /**
   * Form to create/edit an allocation with an activity.
   *
   * @param id the actor id
   * @param allocatedActivityId the allocated activity id (0 for create)
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result manageAllocatedActivity(Long id, Long allocatedActivityId) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // initiate the form with the template
    Form<TimesheetActivityAllocatedActorFormData> allocatedActivityForm =
        allocatedActivityFormTemplate;

    // edit case: inject values
    if (!allocatedActivityId.equals(Long.valueOf(0))) {

      TimesheetActivityAllocatedActor allocatedActivity =
          TimesheetDao.getTimesheetActivityAllocatedActorById(allocatedActivityId);

      // security: the actor must be related to the object
      if (!allocatedActivity.actor.id.equals(id)) {
        return forbidden(views.html.error.access_forbidden.render(""));
      }

      allocatedActivityForm =
          allocatedActivityFormTemplate.fill(
              new TimesheetActivityAllocatedActorFormData(id, allocatedActivity));

      // add the custom attributes values
      this.getCustomAttributeManagerService()
          .fillWithValues(
              allocatedActivityForm, TimesheetActivityAllocatedActor.class, allocatedActivityId);
    } else {
      // add the custom attributes default values
      this.getCustomAttributeManagerService()
          .fillWithValues(allocatedActivityForm, TimesheetActivityAllocatedActor.class, null);
    }

    return ok(views.html.core.actor.allocated_activity_manage.render(actor, allocatedActivityForm));
  }
  /**
   * Display the allocations (portfolio entry and activity) of the actor.
   *
   * @param id the actor id
   * @param pagePortfolioEntry the current page for the portfolio entry allocations
   * @param pageActivity the current page for the activity allocations
   * @param viewAllActivities set to true if all activities (including the past ones) must be
   *     displayed
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_VIEW_DYNAMIC_PERMISSION)
  public Result allocationDetails(
      Long id, Integer pagePortfolioEntry, Integer pageActivity, Boolean viewAllActivities) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // construct the "portfolio entry" allocations tables

    Pagination<PortfolioEntryResourcePlanAllocatedActor> portfolioEntryPagination =
        PortfolioEntryResourcePlanDAO.getPEPlanAllocatedActorAsPaginationByActorAndActive(id, true);
    portfolioEntryPagination.setCurrentPage(pagePortfolioEntry);
    portfolioEntryPagination.setPageQueryName("pagePortfolioEntry");

    List<PortfolioEntryResourcePlanAllocatedActorListView> allocationListView =
        new ArrayList<PortfolioEntryResourcePlanAllocatedActorListView>();
    for (PortfolioEntryResourcePlanAllocatedActor allocatedActor :
        portfolioEntryPagination.getListOfObjects()) {
      allocationListView.add(new PortfolioEntryResourcePlanAllocatedActorListView(allocatedActor));
    }

    Set<String> columnsToHide = new HashSet<String>();
    columnsToHide.add("editActionLink");
    columnsToHide.add("removeActionLink");
    columnsToHide.add("followPackageDates");
    columnsToHide.add("actor");
    if (!getBudgetTrackingService().isActive()) {
      columnsToHide.add("currency");
      columnsToHide.add("dailyRate");
      columnsToHide.add("forecastDays");
      columnsToHide.add("forecastDailyRate");
    }

    Table<PortfolioEntryResourcePlanAllocatedActorListView> portfolioEntryTable =
        this.getTableProvider()
            .get()
            .portfolioEntryResourcePlanAllocatedActor
            .templateTable
            .fill(allocationListView, columnsToHide);

    portfolioEntryTable.setLineAction(
        new IColumnFormatter<PortfolioEntryResourcePlanAllocatedActorListView>() {
          @Override
          public String apply(
              PortfolioEntryResourcePlanAllocatedActorListView
                  portfolioEntryResourcePlanAllocatedActorListView,
              Object value) {
            return controllers.core.routes.PortfolioEntryPlanningController.resources(
                    portfolioEntryResourcePlanAllocatedActorListView.portfolioEntryId)
                .url();
          }
        });

    // construct the "activity" allocations tables

    Pagination<TimesheetActivityAllocatedActor> activityPagination =
        TimesheetDao.getTimesheetActivityAllocatedActorAsPaginationByActor(id, !viewAllActivities);
    activityPagination.setCurrentPage(pageActivity);
    activityPagination.setPageQueryName("pageActivity");

    List<TimesheetActivityAllocatedActorListView> activityAllocationListView =
        new ArrayList<TimesheetActivityAllocatedActorListView>();
    for (TimesheetActivityAllocatedActor allocatedActor : activityPagination.getListOfObjects()) {
      activityAllocationListView.add(new TimesheetActivityAllocatedActorListView(allocatedActor));
    }

    Set<String> columnsToHideForActivity = new HashSet<String>();
    columnsToHideForActivity.add("actor");

    Table<TimesheetActivityAllocatedActorListView> activityTable =
        this.getTableProvider()
            .get()
            .timesheetActivityAllocatedActor
            .templateTable
            .fill(activityAllocationListView, columnsToHideForActivity);

    return ok(
        views.html.core.actor.actor_allocation_details.render(
            actor,
            portfolioEntryTable,
            portfolioEntryPagination,
            activityTable,
            activityPagination,
            viewAllActivities));
  }
  /**
   * Display the gantt of allocations of the actor.
   *
   * @param id the actor id
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_VIEW_DYNAMIC_PERMISSION)
  public Result allocation(Long id) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // prepare the data (to order them)
    SortableCollection<DateSortableObject> sortableCollection = new SortableCollection<>();
    for (PortfolioEntryResourcePlanAllocatedActor allocatedActor :
        PortfolioEntryResourcePlanDAO.getPEPlanAllocatedActorAsListByActorAndActive(id, true)) {
      if (allocatedActor.endDate != null) {
        sortableCollection.addObject(
            new DateSortableObject(allocatedActor.endDate, allocatedActor));
      }
    }
    for (TimesheetActivityAllocatedActor allocatedActivity :
        TimesheetDao.getTimesheetActivityAllocatedActorAsListByActor(id, true)) {
      if (allocatedActivity.endDate != null) {
        sortableCollection.addObject(
            new DateSortableObject(allocatedActivity.endDate, allocatedActivity));
      }
    }

    // construct the gantt

    List<SourceItem> items = new ArrayList<SourceItem>();

    for (DateSortableObject dateSortableObject : sortableCollection.getSorted()) {

      if (dateSortableObject.getObject() instanceof PortfolioEntryResourcePlanAllocatedActor) {

        PortfolioEntryResourcePlanAllocatedActor allocatedActor =
            (PortfolioEntryResourcePlanAllocatedActor) dateSortableObject.getObject();

        // get the from date
        Date from = allocatedActor.startDate;

        // get the to date
        Date to = allocatedActor.endDate;

        // get the portfolio entry
        Long portfolioEntryId =
            allocatedActor.portfolioEntryResourcePlan.lifeCycleInstancePlannings.get(0)
                .lifeCycleInstance
                .portfolioEntry
                .id;
        PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(portfolioEntryId);

        String packageName =
            allocatedActor.portfolioEntryPlanningPackage != null
                ? allocatedActor.portfolioEntryPlanningPackage.getName()
                : "";

        SourceItem item = new SourceItem(portfolioEntry.getName(), packageName);

        String cssClass = null;

        if (from != null) {

          to = JqueryGantt.cleanToDate(from, to);
          cssClass = "";

        } else {

          from = to;
          cssClass = "diamond diamond-";
        }

        if (allocatedActor.isConfirmed) {
          cssClass += "success";
        } else {
          cssClass += "warning";
        }

        SourceDataValue dataValue =
            new SourceDataValue(
                controllers.core.routes.PortfolioEntryPlanningController.resources(
                        portfolioEntry.id)
                    .url(),
                null,
                null,
                null,
                null);

        item.values.add(
            new SourceValue(
                from,
                to,
                "",
                views
                    .html
                    .framework_views
                    .parts
                    .formats
                    .display_number
                    .render(allocatedActor.days, null, false)
                    .body(),
                cssClass,
                dataValue));

        items.add(item);
      }

      if (dateSortableObject.getObject() instanceof TimesheetActivityAllocatedActor) {

        TimesheetActivityAllocatedActor allocatedActivity =
            (TimesheetActivityAllocatedActor) dateSortableObject.getObject();

        // get the from date
        Date from = allocatedActivity.startDate;

        // get the to date
        Date to = allocatedActivity.endDate;

        SourceItem item = new SourceItem(allocatedActivity.timesheetActivity.getName(), "");

        String cssClass = null;

        if (from != null) {

          to = JqueryGantt.cleanToDate(from, to);
          cssClass = "";

        } else {

          from = to;
          cssClass = "diamond diamond-";
        }

        cssClass += "info";

        SourceDataValue dataValue =
            new SourceDataValue(
                controllers.core.routes.ActorController.allocationDetails(actor.id, 0, 0, false)
                    .url(),
                null,
                null,
                null,
                null);

        item.values.add(
            new SourceValue(
                from,
                to,
                "",
                views
                    .html
                    .framework_views
                    .parts
                    .formats
                    .display_number
                    .render(allocatedActivity.days, null, false)
                    .body(),
                cssClass,
                dataValue));

        items.add(item);
      }
    }

    String ganttSource = "";
    try {
      ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
      ganttSource = ow.writeValueAsString(items);
    } catch (JsonProcessingException e) {
      Logger.error(e.getMessage());
    }

    return ok(views.html.core.actor.actor_allocation.render(actor, ganttSource));
  }
  /** Process the save of an actor (create and edit cases). */
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result save() {

    // bind the form
    Form<ActorFormData> boundForm = formTemplate.bindFromRequest();

    if (boundForm.hasErrors()
        || this.getCustomAttributeManagerService().validateValues(boundForm, Actor.class)) {

      if (boundForm.data().get("id") != null) { // edit case
        // get the actor
        Long id = Long.valueOf(boundForm.data().get("id"));
        Actor actor = ActorDao.getActorById(id);
        return ok(
            views.html.core.actor.actor_edit.render(
                actor, boundForm, ActorDao.getActorTypeActiveAsVH()));
      } else { // new case
        return ok(
            views.html.core.actor.actor_new.render(boundForm, ActorDao.getActorTypeActiveAsVH()));
      }
    }

    ActorFormData actorFormData = boundForm.get();

    // check the uid is not already used by another actor
    if (actorFormData.uid != null && !actorFormData.uid.equals("")) {
      Actor testActor = ActorDao.getActorByUid(actorFormData.uid);
      if (testActor != null) { // edit case

        if (actorFormData.id != null) {
          if (!testActor.id.equals(actorFormData.id)) {
            boundForm.reject("uid", Msg.get("object.actor.uid.invalid"));
            Actor actor = ActorDao.getActorById(actorFormData.id);
            return ok(
                views.html.core.actor.actor_edit.render(
                    actor, boundForm, ActorDao.getActorTypeActiveAsVH()));
          }
        } else { // new case
          boundForm.reject("uid", Msg.get("object.actor.uid.invalid"));
          return ok(
              views.html.core.actor.actor_new.render(boundForm, ActorDao.getActorTypeActiveAsVH()));
        }
      }
    }

    Actor actor = null;

    if (actorFormData.id != null) { // edit case

      actor = ActorDao.getActorById(actorFormData.id);
      actorFormData.fill(actor);
      actor.update();

      Utilities.sendSuccessFlashMessage(Msg.get("core.actor.edit.successful"));

    } else { // new case

      actor = new Actor();
      actorFormData.fill(actor);
      actor.save();

      Utilities.sendSuccessFlashMessage(Msg.get("core.actor.new.successful"));
    }

    // save the custom attributes
    this.getCustomAttributeManagerService().validateAndSaveValues(boundForm, Actor.class, actor.id);

    return redirect(controllers.core.routes.ActorController.view(actor.id));
  }