@Override
  public void doView(RenderRequest request, RenderResponse response)
      throws PortletException, IOException {
    try {
      String view = VIEW_FORM_PAGE;
      String viewType = request.getParameter("viewType");
      if (viewType == null) {
        viewType = (String) request.getPortletSession().getAttribute("viewType");
      }
      // Set global preferences
      request.setAttribute(TITLE, request.getPreferences().getValue(PREF_TITLE, null));
      request.setAttribute(
          INTRODUCTION_MESSAGE, request.getPreferences().getValue(PREF_INTRODUCTION_MESSAGE, null));

      User user = PortalUtils.getUser(request);
      Project project = PortalUtils.getProject(request);

      Task task = (Task) request.getPortletSession().getAttribute("task");

      int projectId = project == null ? -1 : project.getId();
      String projectIdOfLists = request.getParameter(PROJECT_ID_OF_LISTS);
      int pidOfLists = projectIdOfLists == null ? -1 : Integer.parseInt(projectIdOfLists);

      LOG.debug("doView: pidOfLists -- " + pidOfLists);

      // Clean up session
      request.getPortletSession().removeAttribute(VIEW_TYPE);
      request.getPortletSession().removeAttribute(PROJECT_ID_OF_LISTS);

      if (SAVE_FAILURE.equals(viewType)) {
        // Prep the form to show errors...
        request.setAttribute(
            ACTION_ERROR, request.getPreferences().getValue(PREF_FAILURE_MESSAGE, null));
        // Show the form with any errors provided
        PortalUtils.processErrors(request, task.getErrors());
      } else if (SAVE_SUCCESS.equals(viewType)) {
        // Save Success
        request.setAttribute(
            SUCCESS_MESSAGE, request.getPreferences().getValue(PREF_SUCCESS_MESSAGE, null));
        view = VIEW_MESSAGE_PAGE;
      } else {
        if (!user.isLoggedIn()) {
          // If user is not logged in, redirect
          view = VIEW_MESSAGE_PAGE;
          request.setAttribute(ACTION_ERROR, "You need to be logged in to perform this action");
        } else if (projectId <= 0) {
          request.setAttribute(ACTION_ERROR, "No project was specified");
          view = VIEW_MESSAGE_PAGE;
        } else {
          view = VIEW_FORM_PAGE;
          try {
            Connection db = PortalUtils.useConnection(request);

            int userProfileId = user.getProfileProjectId();
            Project userProfile;
            if (userProfileId == -1) {
              view = VIEW_MESSAGE_PAGE;
              request.setAttribute(ACTION_ERROR, "No profile is available to bookmark.");
            } else {
              userProfile = ProjectUtils.loadProject(userProfileId);
              if (pidOfLists == -1) {
                pidOfLists = userProfile.getId();
              }
              // check the user has permissions to add/delete from lists for the project whose lists
              // are being modified
              // these will be used by the view to dynamically show/hide functionality
              request.setAttribute(
                  CAN_ADD_LIST, ProjectUtils.hasAccess(pidOfLists, user, "project-lists-add"));
              request.setAttribute(
                  CAN_DELETE_FROM_LIST,
                  ProjectUtils.hasAccess(pidOfLists, user, "project-lists-delete"));

              ProjectList projectList = findUserProjects(db, user);
              ProjectList availableProjects = new ProjectList();
              // Profile needs to appear on top so remove it from list and don't add twice
              availableProjects.add(userProfile);
              for (int i = 0; i != projectList.size(); i++) {
                Project p = projectList.get(i);
                if (p.getId() != userProfile.getId()) {
                  availableProjects.add(p);
                }
              }

              TaskCategoryList availableLists = getAvailableLists(db, pidOfLists);

              String errorMessage = (String) request.getPortletSession().getAttribute(ACTION_ERROR);
              if (StringUtils.hasText(errorMessage)) {
                request.setAttribute(ACTION_ERROR, errorMessage);
              }

              Map<Integer, TaskCategory> usedLists =
                  findExistingTaskCategorysForProjects(db, pidOfLists, project.getId());
              request.setAttribute(PROJECT_ID_OF_LISTS, pidOfLists);
              request.setAttribute(PROJECT, project);
              request.setAttribute(AVAILABLE_LISTS, availableLists);
              request.setAttribute(USER_PROFILE, userProfile);
              request.setAttribute(AVAILABLE_PROJECTS, availableProjects);
              request.setAttribute(USED_LIST_MAP, usedLists);
            }
          } catch (SQLException e) {
            e.printStackTrace();
            view = VIEW_MESSAGE_PAGE;
            request.setAttribute(
                ACTION_ERROR, "An error occurred processing your request. Please try again.");
          }
        }
      }
      // Clean up session
      request.getPortletSession().removeAttribute(ACTION_ERROR);
      PortletContext context = getPortletContext();
      PortletRequestDispatcher requestDispatcher = context.getRequestDispatcher(view);
      requestDispatcher.include(request, response);
    } catch (Exception e) {
      e.printStackTrace();
      throw new PortletException(e);
    }
  }
  @Override
  public void processAction(ActionRequest request, ActionResponse response)
      throws PortletException, IOException {
    String ctx = request.getContextPath();
    boolean isClose = "true".equals(request.getParameter("close"));

    if (isClose) {
      // Clean up the session
      LOG.debug("Closing the form");
      request.getPortletSession().removeAttribute(VIEW_TYPE);
      response.sendRedirect(ctx + CLOSE_PAGE);
      return;
    }

    int projectIdToBookmark = Integer.valueOf(request.getParameter(PROJECT_ID_TO_BOOKMARK));
    int projectIdOfLists = Integer.valueOf(request.getParameter(PROJECT_ID_OF_LISTS));
    String newListName = request.getParameter(NEW_LIST_NAME);

    // If the user selected an item in the drop-down, then that means they are
    // changing lists
    int pidToCompare = Integer.valueOf(request.getParameter("pidToCompare"));
    boolean isChangePidOfLists = pidToCompare != projectIdOfLists;
    if (isChangePidOfLists) {
      LOG.debug("A new project has been selected: " + projectIdOfLists);
      response.setRenderParameter(PROJECT_ID_OF_LISTS, String.valueOf(projectIdOfLists));
      return;
    }

    try {
      LOG.debug("Saving the form...");

      boolean isSuccess;

      User user = PortalUtils.getUser(request);
      int userId = user.getId();
      Connection db = PortalUtils.useConnection(request);
      Project projectOfLists = new Project(db, projectIdOfLists);
      Project projectToBookmark = new Project(db, projectIdToBookmark);
      Collection<Integer> listIds = getListIds(request.getParameterValues(LIST));
      // verify user can modify lists for project
      boolean isAddNewList = false;
      if (ProjectUtils.hasAccess(projectOfLists.getId(), user, "project-lists-modify")) {

        if (!StringUtils.hasText(newListName) && (listIds.size() == 0)) {
          System.out.println("Error need to show From");
          request.getPortletSession().setAttribute(ACTION_ERROR, "Choose a list or create one");
          request.getPortletSession().setAttribute(VIEW_TYPE, VIEW_FORM_PAGE);
          return;
        }

        if (StringUtils.hasText(newListName)) {
          if (!ProjectUtils.hasAccess(projectOfLists.getId(), user, "project-lists-add")) {
            request
                .getPortletSession()
                .setAttribute(ACTION_ERROR, "Not authorized to create new list");
            request.getPortletSession().setAttribute(VIEW_TYPE, VIEW_FORM_PAGE);
            return;
          }
          int newListId = saveNewList(db, projectIdOfLists, newListName);
          if (newListId == -1) {
            request.getPortletSession().setAttribute(ACTION_ERROR, "Unable to create new list.");
            request.getPortletSession().setAttribute(VIEW_TYPE, SAVE_FAILURE);
            return;
          } else {
            listIds.add(newListId);
            isAddNewList = true;
          }
        }
        TaskList existingTasks =
            findExistingTasksForProjects(db, projectIdOfLists, projectIdToBookmark);
        // check to see if the user is deleting tasks (listItems)
        if ((isAddNewList && existingTasks.size() > listIds.size() - 1)
            || !isAddNewList && existingTasks.size() > listIds.size()) {
          if (!ProjectUtils.hasAccess(projectOfLists.getId(), user, "project-lists-delete")) {
            request
                .getPortletSession()
                .setAttribute(ACTION_ERROR, "Not authorized to delete items");
            request.getPortletSession().setAttribute(VIEW_TYPE, VIEW_FORM_PAGE);
            return;
          } else {
            deleteFromLists(db, existingTasks, listIds);
          }
        }
        isSuccess =
            saveToLists(
                db,
                existingTasks,
                listIds,
                userId,
                projectIdToBookmark,
                projectToBookmark.getTitle(),
                projectIdOfLists,
                request);
      } else {
        isSuccess = false;
        request.getPortletSession().setAttribute(ACTION_ERROR, "Not authorized to bookmark");
      }

      if (isSuccess) {
        // Close the panel, everything went well
        response.sendRedirect(ctx + "/close_panel_refresh.jsp");
      } else {
        request.getPortletSession().setAttribute(VIEW_TYPE, SAVE_FAILURE);
      }
    } catch (SQLException e) {
      e.printStackTrace();
      throw new RuntimeException(e);
    }
  }
  public boolean execute(ComponentContext context) {
    int businessEmailType = -1;
    int businessAddressType = -1;
    int businessPhoneType = -1;
    int advertisementLeadSourceType = -1;
    int webLeadSourceType = -1;
    int businessFaxType = -1;
    int stageUnclaimed = -1;
    int stageSuggested = -1;
    int stageRequested = -1;

    String url = "";
    String domainName = "";
    String code = "";
    String clientId = "";

    // A reusable connection
    CRMConnection connection = null;

    // Populate the variables
    if (!StringUtils.hasText(context.getParameter("suite.url"))) {
      url = context.getApplicationPrefs().get("CONCURSIVE_CRM.SERVER");
    } else {
      url = context.getParameter("suite.url");
    }

    if (!StringUtils.hasText(context.getParameter("suite.domainName"))) {
      domainName = context.getApplicationPrefs().get("CONCURSIVE_CRM.ID");
    } else {
      domainName = context.getParameter("suite.domainName");
    }

    if (!StringUtils.hasText(context.getParameter("suite.code"))) {
      code = context.getApplicationPrefs().get("CONCURSIVE_CRM.CODE");
    } else {
      code = context.getParameter("suite.code");
    }

    clientId = context.getApplicationPrefs().get("CONCURSIVE_CRM.CLIENT");

    // Create the connection
    connection = new CRMConnection();
    connection.setUrl(url);
    connection.setId(domainName);
    connection.setCode(code);
    // connection.setClientId(clientId);
    // NOTE: the CRMConnection invalidates sessions preventing this from working
    /*if (cookie != null) {
      connection.setCookie(cookie);
    }*/

    // Related info is needed for updating an Account
    // Load a Hashmap to pass these values around...
    HashMap<String, Integer> lookupListValues = new HashMap<String, Integer>();

    // Note: Hacked together as a short term fix to make the components thread-safe.
    businessEmailType =
        this.getIdFromValue(
            context,
            connection,
            "lookupContactEmailTypesList",
            "lookup_contactemail_types",
            "Business");
    lookupListValues.put("businessEmailType", businessEmailType);
    businessPhoneType =
        this.getIdFromValue(
            context,
            connection,
            "lookupContactPhoneTypesList",
            "lookup_contactphone_types",
            "Business");
    lookupListValues.put("businessPhoneType", businessPhoneType);
    businessFaxType =
        this.getIdFromValue(
            context,
            connection,
            "lookupContactPhoneTypesList",
            "lookup_contactphone_types",
            "Business Fax");
    lookupListValues.put("businessFaxType", businessFaxType);
    businessAddressType =
        this.getIdFromValue(
            context,
            connection,
            "lookupContactAddressTypesList",
            "lookup_contactaddress_types",
            "Business");
    lookupListValues.put("businessAddressType", businessAddressType);
    advertisementLeadSourceType =
        this.getIdFromValue(
            context,
            connection,
            "lookupContactSourceList",
            "lookup_contact_source",
            "Advertisement");
    lookupListValues.put("advertisementLeadSourceType", advertisementLeadSourceType);
    webLeadSourceType =
        this.getIdFromValue(
            context, connection, "lookupContactSourceList", "lookup_contact_source", "Web");
    lookupListValues.put("webLeadSourceType", webLeadSourceType);
    stageUnclaimed =
        this.getIdFromValue(
            context, connection, "lookupAccountStageList", "lookup_account_stage", "Unclaimed");
    lookupListValues.put("stageUnclaimed", stageUnclaimed);
    stageSuggested =
        this.getIdFromValue(
            context, connection, "lookupAccountStageList", "lookup_account_stage", "Suggested");
    lookupListValues.put("stageSuggested", stageSuggested);
    stageRequested =
        this.getIdFromValue(
            context, connection, "lookupAccountStageList", "lookup_account_stage", "Requested");
    lookupListValues.put("stageRequested", stageRequested);

    // Find the account's orgId
    int orgId = -1;
    String orgName = null;
    {
      // Add Meta Info with fields required
      ArrayList<String> meta = new ArrayList<String>();
      meta.add("orgId");
      meta.add("name");
      connection.setTransactionMeta(meta);

      // Find the account id
      DataRecord record = new DataRecord();
      record.setName("accountList");
      record.setAction(DataRecord.SELECT);
      record.addField("custom1", context.getParameter("lead.custom1"));
      connection.save(record);

      orgId = Integer.parseInt(connection.getResponseValue("orgId"));
      orgName = connection.getResponseValue("name");
    }

    // An orgId to update must exist
    if (orgId == -1) {
      return false;
    }

    // Load the Account Owner's User id
    int ownerId = 1;
    {
      // Reuse the value between calls
      String lastNameToUse = "ConnectSales";
      String globalOwnerIdParam = getUniqueName() + ".contactList.lastName." + lastNameToUse;

      // Check the global workflow store
      Integer globalValue = (Integer) context.getGlobalParameter(globalOwnerIdParam);
      if (globalValue != null) {
        System.out.println("UpdateAsAccount-> User |" + lastNameToUse + "| not found on CRM");
        ownerId = globalValue;
      } else {
        // Add Meta Info with fields required
        ArrayList<String> meta = new ArrayList<String>();
        meta.add("userId");
        connection.setTransactionMeta(meta);

        // Find the sales person
        DataRecord record = new DataRecord();
        record.setName("contactList");
        record.setAction(DataRecord.SELECT);
        record.addField("employeesOnly", "1");
        record.addField("lastName", lastNameToUse);
        connection.save(record);

        int foundValue = Integer.parseInt(connection.getResponseValue("userId"));
        context.setGlobalParameterIfAbsent(globalOwnerIdParam, foundValue);
        ownerId = foundValue;
      }
    }

    // Update the matching account
    DataRecord account = new DataRecord();
    account.setAction(DataRecord.UPDATE);
    account.setName("account");
    account.addField("id", orgId);
    account.addField("name", orgName);
    account.addField("enteredBy", "$U{default}");
    account.addField("modifiedBy", "$U{default}");
    // Change the stage of the account
    if (StringUtils.hasText(context.getParameter("lead.stageName"))) {
      account.addField("stageName", context.getParameter("lead.stageName"));
      if (context.getParameter("lead.stageName").equalsIgnoreCase("Unclaimed")) {
        account.addField("stageId", stageUnclaimed);
      } else {
        if (context.getParameter("lead.stageName").equalsIgnoreCase("Requested")) {
          account.addField("stageId", stageRequested);
        } else {
          if (context.getParameter("lead.stageName").equalsIgnoreCase("Suggested")) {
            account.addField("stageId", stageSuggested);
          }
        }
      }
    } else {
      account.addField("stageName", "Unclaimed");
      account.addField("stageId", stageUnclaimed);
    }
    connection.save(account);

    // Will be adding several records, so make sure we add them as a group...
    connection.setAutoCommit(false);

    // Add the user information as a contact...
    // Account record transaction: Contact
    DataRecord contact = new DataRecord();
    contact.setAction(DataRecord.INSERT);
    contact.setShareKey(true);
    contact.setName("contact");
    contact.addField(
        "source", webLeadSourceType > -1 ? webLeadSourceType : advertisementLeadSourceType);
    contact.addField("accessType", "$AT{GENERAL_CONTACT_PUBLIC}");
    contact.addField("orgId", orgId);
    contact.addField("enteredBy", "$U{default}");
    contact.addField("modifiedBy", "$U{default}");
    contact.addField("owner", ownerId);
    if (StringUtils.hasText(context.getParameter("lead.custom1"))) {
      contact.addField("custom1", context.getParameter("lead.custom1"));
    }
    if (StringUtils.hasText(context.getParameter("lead.firstName"))) {
      contact.addField("nameFirst", context.getParameter("lead.firstName"));
    }
    if (StringUtils.hasText(context.getParameter("lead.lastName"))) {
      contact.addField("nameLast", context.getParameter("lead.lastName"));
    }
    if (StringUtils.hasText(context.getParameter("lead.company"))) {
      contact.addField("company", context.getParameter("lead.company"));
    }
    if (StringUtils.hasText(context.getParameter("lead.webPage"))
        && context.getParameter("lead.webPage").indexOf("${") == -1) {
      contact.addField("url", context.getParameter("lead.webPage"));
    }
    connection.save(contact);

    // Account record transaction: Contact's Email Address
    DataRecord email = new DataRecord();
    if (StringUtils.hasText(context.getParameter("lead.businessEmail"))
        && businessEmailType > 0
        && context.getParameter("lead.businessEmail").indexOf("${") == -1) {
      email.setName("contactEmailAddress");
      email.addField("email", context.getParameter("lead.businessEmail").trim());
      email.addField("type", businessEmailType);
      email.addField("contactId", "$C{contact.id}");
      email.addField("enteredBy", "$U{default}");
      email.addField("modifiedBy", "$U{default}");
      email.setAction(DataRecord.INSERT);
      connection.save(email);
    }

    // Submit everything...
    boolean success = connection.commit();
    if (!success) {
      System.out.println("UpdateAsAccount-> Commit message: " + connection.getLastResponse());
      return false;
    }
    return true;
  }