Package org.olat.admin.user

Source Code of org.olat.admin.user.UserSearchController

/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS,
* <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/

package org.olat.admin.user;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.olat.basesecurity.ManagerFactory;
import org.olat.basesecurity.events.MultiIdentityChosenEvent;
import org.olat.basesecurity.events.SingleIdentityChosenEvent;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.Windows;
import org.olat.core.gui.components.Component;
import org.olat.core.gui.components.form.Form;
import org.olat.core.gui.components.link.Link;
import org.olat.core.gui.components.link.LinkFactory;
import org.olat.core.gui.components.panel.Panel;
import org.olat.core.gui.components.table.StaticColumnDescriptor;
import org.olat.core.gui.components.table.Table;
import org.olat.core.gui.components.table.TableController;
import org.olat.core.gui.components.table.TableEvent;
import org.olat.core.gui.components.table.TableGuiConfiguration;
import org.olat.core.gui.components.table.TableMultiSelectEvent;
import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.ControllerEventListener;
import org.olat.core.gui.control.DefaultController;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.generic.ajax.autocompletion.AutoCompleterController;
import org.olat.core.gui.control.generic.ajax.autocompletion.EntriesChosenEvent;
import org.olat.core.gui.control.generic.ajax.autocompletion.ListProvider;
import org.olat.core.gui.control.generic.ajax.autocompletion.ListReceiver;
import org.olat.core.gui.control.state.ControllerState;
import org.olat.core.gui.formelements.AbstractFormElement;
import org.olat.core.gui.formelements.FormElement;
import org.olat.core.gui.formelements.StaticSingleSelectionElement;
import org.olat.core.gui.formelements.TextElement;
import org.olat.core.gui.translator.PackageTranslator;
import org.olat.core.gui.translator.Translator;
import org.olat.core.id.Identity;
import org.olat.core.id.Roles;
import org.olat.core.id.User;
import org.olat.core.id.UserConstants;
import org.olat.core.logging.Tracing;
import org.olat.core.util.StringHelper;
import org.olat.core.util.Util;
import org.olat.user.UserManager;
import org.olat.user.propertyhandlers.UserPropertyHandler;

/**
* Initial Date:  Jul 29, 2003
*
* @author Felix Jost, Florian Gnaegi
*
* <pre>
* Comment: 
* Subworkflow that allows the user to search for a user and choose the user from
* the list of users that match the search criteria. Users can be searched by
* <ul>
* <li />
* Username
* <li />
* First name
* <li />
* Last name
* <li />
* Email address
* </ul>
*
* </pre>
*
* Events:<br>
*         Fires a SingleIdentityChoosenEvent when an identity has been chosen
*         which contains the choosen identity<br>
*         Fires a MultiIdentityChoosenEvent when multiples identities have been
*         chosen which contains the choosen identities<br>
*         <p>
*         Optionally set the useMultiSelect boolean to true which allows to
*         select multiple identities from within the search results.
*/
public class UserSearchController extends DefaultController implements ControllerEventListener {
  private static final String PACKAGE = UserSearchController.class.getPackage().getName();
  private static final String VELOCITY_ROOT = Util.getPackageVelocityRoot(PACKAGE);

  private static final String ACTION_SINGLESELECT_CHOOSE = "ssc";
  private static final String ACTION_MULTISELECT_CHOOSE = "msc";
 
  private VelocityContainer myContent;
  private Panel searchPanel;
  private UserSearchForm searchform;
  private TableController tableCtr;
  private UserTableDataModel tdm;
  private List<Identity> foundIdentities = new ArrayList<Identity>();
  private Translator pT;
  private Link backLink;
  private boolean useMultiSelect = false;
 
  private AutoCompleterController autocompleterC;
  private String actionKeyChoose;

  private static final String STATE_SEARCHFORM = "searchform";
  private static final String STATE_RESULTS = "results";
 
  public static final String ACTION_KEY_CHOOSE = "action.choose";
  public static final String ACTION_KEY_CHOOSE_FINISH = "action.choose.finish";
 
  /**
   * @param ureq
   * @param wControl
   * @param cancelbutton
   */
  public UserSearchController(UserRequest ureq, WindowControl wControl, boolean cancelbutton) {
    this(ureq, wControl, cancelbutton, false, false);
  }

  /**
   * @param ureq
   * @param windowControl
   * @param cancelbutton
   * @param userMultiSelect
   * @param statusEnabled
   * @param actionKeyChooseFinish
   */
  public UserSearchController(UserRequest ureq, WindowControl windowControl, boolean cancelbutton, boolean userMultiSelect, boolean statusEnabled, String actionKeyChooseFinish) {
    this(ureq, windowControl, cancelbutton, userMultiSelect, statusEnabled);
    this.actionKeyChoose = actionKeyChooseFinish;
  }

  /**
   * @param ureq
   * @param wControl
   * @param cancelbutton
   * @param userMultiSelect
   * @param statusEnabled
   */
  public UserSearchController(UserRequest ureq, WindowControl wControl, boolean cancelbutton, boolean userMultiSelect, boolean statusEnabled) {
    super(wControl);
    this.useMultiSelect = userMultiSelect;
    this.actionKeyChoose = ACTION_KEY_CHOOSE;
   
    pT = new PackageTranslator(PACKAGE, ureq.getLocale());
    pT = UserManager.getInstance().getPropertyHandlerTranslator(pT);
    myContent = new VelocityContainer("olatusersearch", VELOCITY_ROOT + "/usersearch.html", pT, this);
   
    backLink = LinkFactory.createButton("btn.back", myContent, this);
   
    searchPanel = new Panel("usersearchPanel");
    searchPanel.addListener(this);
    myContent.put("usersearchPanel", searchPanel);

    if (ureq.getUserSession()==null) {
      Tracing.logError("UserSearchController<init>: session is null!", UserSearchController.class);
    } else if (ureq.getUserSession().getRoles()==null) {
      Tracing.logError("UserSearchController<init>: roles is null!", UserSearchController.class);
    }
    boolean isAdmin = ureq.getUserSession().getRoles().isOLATAdmin();
    searchform = new UserSearchForm("usersearchform", pT, isAdmin, cancelbutton, statusEnabled);
    searchform.addListener(this);
    searchPanel.setContent(searchform);
 
    myContent.contextPut("noList","false");     
    myContent.contextPut("showButton","false");
   
    boolean ajax = Windows.getWindows(ureq).getWindowManager().isAjaxEnabled();
    final Locale loc = ureq.getLocale();
    if (ajax) {
      // insert a autocompleter search
      ListProvider provider = new ListProvider() {
        public void getResult(String searchValue, ListReceiver receiver) {
          Map<String, String> userProperties = new HashMap<String, String>();
          userProperties.put(UserConstants.FIRSTNAME, searchValue);
          userProperties.put(UserConstants.LASTNAME, searchValue);
          userProperties.put(UserConstants.EMAIL, searchValue);
          // FIXME:fg:cg: 13.03.08: User-Properties problem with undefine properties;
//          userProperties.put(UserConstants.INSTITUTIONALEMAIL, searchValue);
//          userProperties.put(UserConstants.INSTITUTIONALUSERIDENTIFIER, searchValue);

          // search in all fileds -> non intersection search
          List res = searchUsers(searchValue,  userProperties, false);
          int maxEntries = 15;
          boolean hasMore = false;
          for (Iterator it_res = res.iterator(); (hasMore=it_res.hasNext()) && maxEntries > 0;) {
            maxEntries--;
            Identity ident = (Identity) it_res.next();
            User u = ident.getUser();
            String login = ident.getName();
            String first = u.getProperty(UserConstants.FIRSTNAME, loc);
            String last = u.getProperty(UserConstants.LASTNAME, loc);
            //String instId = u.getProperty(UserConstants.INSTITUTIONALUSERIDENTIFIER, loc);
            //receiver.addEntry(login, last + " " + first + (StringHelper.containsNonWhitespace(instId) ? " (" + instId + ")": ""));
            receiver.addEntry(login, last + " " + first);
          }         
          if(hasMore){
            receiver.addEntry(".....",".....");
          }
        }
      };
      autocompleterC = new AutoCompleterController(ureq, getWindowControl(), provider, "-", false);
      autocompleterC.addControllerListener(this);
      myContent.put("autocompletionsearch", autocompleterC.getInitialComponent());
    }
   
    setInitialComponent(myContent);
    setState(STATE_SEARCHFORM);
  }

  /**
   * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
   *      org.olat.core.gui.components.Component,
   *      org.olat.core.gui.control.Event)
   */
  public void event(UserRequest ureq, Component source, Event event) {
    if (source == backLink) {   
      myContent.contextPut("noList","false");     
      myContent.contextPut("showButton","false");
      searchPanel.popContent();
      setState(STATE_SEARCHFORM);
    } else if (source == searchform) {
      if (event == Form.EVNT_VALIDATION_OK) {
        // form validation was ok
       
        String login = searchform.getTextElement("login").getValue();
        // build user fields search map
        Map<String, String> userPropertiesSearch = new HashMap<String, String>();       
        for (UserPropertyHandler userPropertyHandler : searchform.userPropertyHandlers) {
          if (userPropertyHandler == null) continue;
          FormElement ui = searchform.getFormElement(userPropertyHandler.getName());
          String uiValue = userPropertyHandler.getStringValue(ui);
          if (StringHelper.containsNonWhitespace(uiValue)) {
            userPropertiesSearch.put(userPropertyHandler.getName(), uiValue);
          }
        }
        if (userPropertiesSearch.isEmpty()) userPropertiesSearch = null;
        myContent.contextPut("showButton","true");   
        TableGuiConfiguration tableConfig = new TableGuiConfiguration();
        tableConfig.setTableEmptyMessage(pT.translate("error.no.user.found"));
        tableConfig.setDownloadOffered(false);// no download because user should not download user-list

        if (tableCtr != null) tableCtr.dispose();
        tableCtr = new TableController(tableConfig, ureq, getWindowControl(), pT, this);
        Roles roles = ureq.getUserSession().getRoles();
        boolean isAdministrativeUser = (roles.isAuthor() || roles.isGroupManager() || roles.isUserManager() || roles.isOLATAdmin());
        tdm = new UserTableDataModel(searchUsers(login,  userPropertiesSearch, true), ureq.getLocale(), isAdministrativeUser);
        // add the data column descriptors
        tdm.addColumnDescriptors(tableCtr, null);
        // add the action columns
        if (useMultiSelect) {
          // add multiselect action
          tableCtr.addMultiSelectAction(this.actionKeyChoose, ACTION_MULTISELECT_CHOOSE);
        } else {
          // add single column selec action
          tableCtr.addColumnDescriptor(new StaticColumnDescriptor(ACTION_SINGLESELECT_CHOOSE, "table.header.action", myContent
              .getTranslator().translate("action.choose")));
        }
       
       
        tableCtr.setTableDataModel(tdm);
        tableCtr.setMultiSelect(useMultiSelect);
        searchPanel.pushContent(tableCtr.getInitialComponent());
        setState(STATE_RESULTS);
      } else if (event == Form.EVNT_FORM_CANCELLED) {
        fireEvent(ureq, Event.CANCELLED_EVENT);
      }
    }
  }

  /**
   * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
   *      org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
   */
  public void event(UserRequest ureq, Controller source, Event event) {
    if (source == tableCtr) {
      if (event.getCommand().equals(Table.COMMANDLINK_ROWACTION_CLICKED)) {
        TableEvent te = (TableEvent) event;
        if (te.getActionId().equals(ACTION_SINGLESELECT_CHOOSE)) {
          int rowid = te.getRowId();
          Identity foundIdentity = (Identity)tdm.getObject(rowid);
          foundIdentities.add(foundIdentity);
          // Tell parentController that a subject has been found
          fireEvent(ureq, new SingleIdentityChosenEvent(foundIdentity));
        }
      } else if (event.getCommand().equals(Table.COMMAND_MULTISELECT)) {
        TableMultiSelectEvent tmse = (TableMultiSelectEvent) event;
        if (tmse.getAction().equals(ACTION_MULTISELECT_CHOOSE)) {
          foundIdentities = tdm.getObjects(tmse.getSelection());
          fireEvent(ureq, new MultiIdentityChosenEvent(foundIdentities));
        }
      }
    } else if (source == autocompleterC) {
      EntriesChosenEvent ece = (EntriesChosenEvent)event;
      List res = ece.getEntries();
      // if we get the event, we have a result
      String mySel = res.isEmpty() ? null : (String) res.get(0);
      if (( mySel == null) || mySel.trim().equals("")) {
        getWindowControl().setWarning(pT.translate("error.search.form.notempty"));
        return;
      }
      if(!mySel.startsWith(".....")){
        List identities = searchUsers(mySel, null, false);
        if (identities.size() == 0) {
          getWindowControl().setWarning(pT.translate("error.no.user.found"));
          return;         
        }
        Identity chosenIdent = (Identity) identities.get(0);
        // tell that an identity has been chosen
        fireEvent(ureq, new SingleIdentityChosenEvent(chosenIdent));
      }
    }
  }
 
  protected void adjustState(ControllerState cstate, UserRequest ureq) {
    String state = cstate.getSerializedState();
    if (state.equals(STATE_SEARCHFORM)) {
      // we should and can adjust to the searchform
      searchPanel.popContent();
      setState(STATE_SEARCHFORM);
    }
  }
 
  /**
   * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
   */
  protected void doDispose() {
    if (tableCtr != null) {
      tableCtr.dispose();
      tableCtr = null;
    }
    if (autocompleterC != null) {
      autocompleterC.dispose();
      autocompleterC = null;
    }
  }

  /**
   * Can be overwritten by subclassen to search other users or filter users.
   * @param login
   * @param userPropertiesSearch
   * @return
   */
  protected List searchUsers(String login, Map<String, String> userPropertiesSearch, boolean userPropertiesAsIntersectionSearch) {
    return ManagerFactory.getManager().getVisibleIdentitiesByPowerSearch(
      (login.equals("") ? null : login),
      userPropertiesSearch, userPropertiesAsIntersectionSearch,  // in normal search fields are intersected
      null, null, null, null, null);
  }
}


/**
* <pre>
*
* Initial Date:  Jul 29, 2003
*
* @author gnaegi
*
* Comment: 
* The user search form
* </pre>
*/
class UserSearchForm extends Form {
 
  private static final String formIdentifyer = UserSearchForm.class.getCanonicalName();
  private final boolean isAdmin;
  List<UserPropertyHandler> userPropertyHandlers;

  /**
   * @param name
   * @param cancelbutton
   * @param isAdmin if true, no field must be filled in at all, otherwise
   *          validation takes place
   */
  @SuppressWarnings("unused")
  public UserSearchForm(String name, Translator translator, boolean isAdmin, boolean cancelbutton, boolean statusEnabled) {
    super(name, translator);
    this.isAdmin = isAdmin;
    addFormElement("login", new TextElement("search.form.login", 128));
   
    UserManager um = UserManager.getInstance();
    userPropertyHandlers = um.getUserPropertyHandlersFor(formIdentifyer, isAdmin);
    // Add all available user fields to this form
    for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
      if (userPropertyHandler == null) continue;
      FormElement ui = userPropertyHandler.getFormElement(getLocale(), null, formIdentifyer, false);
      addFormElement(userPropertyHandler.getName(), ui);
    }
   
    addSubmitKey("submit.search", "submit");
    if (cancelbutton) setCancelKey("submit.cancel");
  }

  private StaticSingleSelectionElement createStatusSelectionElement() {
    String[] statusKeys = { Integer.toString(Identity.STATUS_ACTIV), Integer.toString(Identity.STATUS_PERMANENT), Integer.toString(Identity.STATUS_LOGIN_DENIED) };
    String[] statusValues = {translate("rightsForm.status.activ"), translate("rightsForm.status.permanent"), translate("rightsForm.status.login_denied")};
    return new StaticSingleSelectionElement("rightsForm.status", statusKeys, statusValues);
  }

  /**
   * @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest)
   */
  public boolean validate() {
    // override for admins
    if (isAdmin) return true;
   
    boolean filled = !getTextElement("login").isEmpty();
    StringBuffer  full = new StringBuffer(getTextElement("login").getValue().trim())
    FormElement lastFormElement = getFormElement("login");
   
    // DO NOT validate each user field => see OLAT-3324
    // this are custom fields in a Search Form
    // the same validation logic can not be applied
    // i.e. email must be searchable and not about getting an error like
    // "this e-mail exists already"
    for (UserPropertyHandler userPropertyHandler : userPropertyHandlers) {
      FormElement ui = getFormElement(userPropertyHandler.getName());
        String uiValue = userPropertyHandler.getStringValue(ui);
        // add value for later non-empty search check
        if (StringHelper.containsNonWhitespace(uiValue)) {
          full.append(uiValue.trim());
          filled = true;
        }else{
          //its an empty field
          filled = filled || false;
        }
        lastFormElement = ui;
    }

    // Don't allow searches with * or %  or @ chars only (wild cards). We don't want
    // users to get a complete list of all OLAT users this easily.
    String fullString = full.toString();
    boolean onlyStar= fullString.matches("^[\\* @\\%]*$");

    if (!filled || onlyStar) {
      // set the error message
      ((AbstractFormElement) lastFormElement).setErrorKey("error.search.form.notempty");
      return false;
    }
    if ( fullString.contains("**") ) {
      ((AbstractFormElement)lastFormElement).setErrorKey("error.search.form.no.wildcard.dublicates");
      return false;
    }   
    int MIN_LENGTH = 4;
    if ( fullString.length() < MIN_LENGTH ) {
      ((AbstractFormElement)lastFormElement).setErrorKey("error.search.form.to.short");
      return false;
    }
    return true;
  }
}
TOP

Related Classes of org.olat.admin.user.UserSearchController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.