/*******************************************************************************
* Imixs Workflow Technology
* Copyright (C) 2003, 2008 Imixs Software Solutions GmbH,
* http://www.imixs.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You can receive a copy of the GNU General Public
* License at http://www.gnu.org/licenses/gpl.html
*
* Contributors:
* Imixs Software Solutions GmbH - initial API and implementation
* Ralph Soika
*
*******************************************************************************/
package org.imixs.marty.profile;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Observes;
import javax.faces.event.AjaxBehaviorEvent;
import javax.inject.Inject;
import javax.inject.Named;
import org.imixs.marty.ejb.ProfileService;
import org.imixs.marty.workflow.WorkflowController;
import org.imixs.marty.workflow.WorkflowEvent;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.ItemCollectionComparator;
import org.imixs.workflow.engine.WorkflowService;
import org.imixs.workflow.engine.lucene.LuceneSearchService;
import org.imixs.workflow.exceptions.AccessDeniedException;
/**
* The UserInputController provides suggest-box behavior based on the JSF 2.0
* Ajax capability to add user names into a ItemValue of a WorkItem.
*
* Usage:
*
* <code>
<marty:userInput value=
"#{workflowController.workitem.itemList['namteam']}"
editmode="true" />
* </code>
*
*
* @author rsoika
* @version 1.0
*/
@Named("userInputController")
@SessionScoped
public class UserInputController implements Serializable {
@Inject
protected WorkflowController workflowController;
@Inject
protected UserController userController;
@EJB
protected WorkflowService workflowService;
private List<ItemCollection> searchResult = null;
private String input = null;
private static final long serialVersionUID = 1L;
private int maxSearchCount = 30;
private static Logger logger = Logger.getLogger(UserInputController.class.getName());
public UserInputController() {
super();
searchResult = new ArrayList<ItemCollection>();
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public int getMaxSearchCount() {
return maxSearchCount;
}
/**
* Set the maximum length of a search result
*
* @param maxSearchCount
*/
public void setMaxSearchCount(int maxSearchCount) {
this.maxSearchCount = maxSearchCount;
}
/**
* This method reset the search and input state.
*/
public void reset() {
searchResult = new ArrayList<ItemCollection>();
input = "";
logger.fine("userInputController reset");
}
/**
* This ajax event method reset the search and input state.
*
* @param event
*/
public void reset(AjaxBehaviorEvent event) {
reset();
}
/**
* This method initializes a JPQL search. The method is triggered by ajax
* events from the userInput.xhtml page. The minimum length of a given input
* search phrase have to be at least 2 characters
*
*/
public void search() {
if (input == null || input.length() < 2)
return;
logger.fine("userInputController search for=" + input);
searchResult = searchProfile(input);
}
/**
* This method returns a list of profile ItemCollections matching the search
* phrase. The search statement includes the items 'txtName', 'txtEmail' and
* 'txtUserName'. The result list is sorted by txtUserName
*
* @param phrase
* - search phrase
* @return - list of matching profiles
*/
public List<ItemCollection> searchProfile(String phrase) {
List<ItemCollection> searchResult = new ArrayList<ItemCollection>();
if (phrase == null || phrase.isEmpty())
return searchResult;
// start lucene search
Collection<ItemCollection> col = null;
try {
phrase = phrase.trim();
phrase = LuceneSearchService.escapeSearchTerm(phrase);
// issue #170
phrase = LuceneSearchService.normalizeSearchTerm(phrase);
String sQuery = "(type:\"profile\") AND (" + phrase + "*)";
logger.finest("searchprofile: " + sQuery);
logger.fine("searchWorkitems: " + sQuery);
col = workflowService.getDocumentService().find(sQuery, 0, -1);
} catch (Exception e) {
logger.warning(" lucene error - " + e.getMessage());
}
for (ItemCollection profile : col) {
searchResult.add(ProfileService.cloneWorkitem(profile));
}
// sort by username..
Collections.sort(searchResult, new ItemCollectionComparator("txtusername", true));
return searchResult;
}
public List<ItemCollection> getSearchResult() {
return searchResult;
}
/**
* This methods adds a new name to a userid list
*
*/
public void add(String aName, List<Object> aList) {
if (aList == null || aName == null || aName.isEmpty())
return;
// trim
aName = aName.trim();
if (!aList.contains(aName)) {
logger.fine("userInputController add '" + aName + "' from list.");
aList.add(aName);
}
// remove empty entries.....
Iterator<Object> i = aList.iterator();
while (i.hasNext()) {
Object oentry = i.next();
if (oentry == null || oentry.toString().isEmpty()) {
i.remove();
}
}
}
/**
* This methods removes a name from the userid list
*/
public void remove(String aName, List<Object> aList) {
if (aList == null || aName == null)
return;
logger.fine("userInputController remove '" + aName + "' from list.");
// in some cases the username can be stored in wrong upper/lower case.
// This is the reason for a special double check
if (aList.contains(aName)) {
aList.remove(aName);
} else {
// here we try to find the entry ignoring upper/lower case ....
for (Object aEntry : aList) {
if (aEntry != null) {
String aValue = aEntry.toString().toLowerCase();
if (aValue.equals(aName.toLowerCase())) {
logger.warning(
"userInputController remove '" + aName + "' from list ignoring upper/lower case!");
aList.remove(aEntry);
break;
}
}
}
}
}
/**
* This method returns a sorted list of profiles for a given userId list
*
* @param aNameList
* - string list with user ids
* @return - list of profiles
*/
public List<ItemCollection> getSortedProfilelist(List<Object> aNameList) {
List<ItemCollection> profiles = new ArrayList<ItemCollection>();
if (aNameList == null)
return profiles;
// add all profile objects....
for (Object aentry : aNameList) {
if (aentry != null && !aentry.toString().isEmpty()) {
ItemCollection profile = userController.getProfile(aentry.toString());
if (profile != null) {
profiles.add(profile);
} else {
// create a dummy entry
profile = new ItemCollection();
profile.replaceItemValue("txtName", aentry.toString());
profile.replaceItemValue("txtUserName", aentry.toString());
profiles.add(profile);
}
}
}
// sort by username..
Collections.sort(profiles, new ItemCollectionComparator("txtUserName", true));
return profiles;
}
/**
* WorkflowEvent listener to reset state
*
* @param workflowEvent
* @throws AccessDeniedException
*/
public void onWorkflowEvent(@Observes WorkflowEvent workflowEvent) throws AccessDeniedException {
// reset state
reset();
}
}