package is.idega.idegaweb.egov.bpm.cases.messages; import is.idega.idegaweb.egov.cases.business.CasesBusiness; import is.idega.idegaweb.egov.cases.presentation.ClosedCases; import is.idega.idegaweb.egov.cases.presentation.HandlerCases; import is.idega.idegaweb.egov.cases.presentation.MyCases; import is.idega.idegaweb.egov.cases.presentation.OpenCases; import is.idega.idegaweb.egov.cases.presentation.PublicCases; import java.net.URL; import java.rmi.RemoteException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.ejb.FinderException; import org.jbpm.graph.exe.ProcessInstance; import org.springframework.beans.factory.annotation.Autowired; import com.idega.block.process.data.Case; import com.idega.block.process.presentation.CaseBlock; import com.idega.block.process.presentation.UserCases; import com.idega.builder.business.BuilderLogic; import com.idega.business.IBOLookup; import com.idega.business.IBOLookupException; import com.idega.business.IBORuntimeException; import com.idega.core.accesscontrol.business.AccessController; import com.idega.core.accesscontrol.business.LoginBusinessBean; import com.idega.core.builder.business.BuilderService; import com.idega.core.builder.business.BuilderServiceFactory; import com.idega.core.builder.data.ICPage; import com.idega.core.component.business.ICObjectBusiness; import com.idega.core.component.data.ICObjectInstance; import com.idega.core.component.data.ICObjectInstanceHome; import com.idega.core.contact.data.Email; import com.idega.data.IDOLookup; import com.idega.data.IDOLookupException; import com.idega.idegaweb.IWApplicationContext; import com.idega.idegaweb.IWMainApplication; import com.idega.idegaweb.egov.bpm.data.CaseProcInstBind; import com.idega.idegaweb.egov.bpm.data.dao.CasesBPMDAO; import com.idega.jbpm.exe.BPMFactory; import com.idega.jbpm.exe.ProcessInstanceW; import com.idega.jbpm.identity.BPMUser; import com.idega.jbpm.identity.BPMUserFactory; import com.idega.jbpm.identity.Role; import com.idega.jbpm.identity.UserPersonalData; import com.idega.jbpm.rights.Right; import com.idega.user.business.UserBusiness; import com.idega.user.data.User; import com.idega.util.CoreConstants; import com.idega.util.CoreUtil; import com.idega.util.ListUtil; import com.idega.util.StringUtil; import com.idega.util.URIParam; import com.idega.util.URIUtil; import com.idega.util.expression.ELUtil; /** * @author <a href="mailto:civilis@idega.com">Vytautas Čivilis</a> * @version $Revision: 1.6 $ * * Last modified: $Date: 2009/01/22 17:29:22 $ by $Author: anton $ */ public class CaseUserImpl { public static final String CHECK_CASE_STATUS = "bpm.check_case_status_for_url"; public static final Logger LOGGER = Logger.getLogger(CaseUserImpl.class.getName()); private User user; private ProcessInstanceW processInstanceW; private BPMUserFactory bpmUserFactory; private BPMFactory bpmFactory; @Autowired private CasesBPMDAO casesBPMDAO = null; private ICObjectInstanceHome icObjectInstanceHome = null; private CasesBusiness casesBusiness = null; private UserBusiness userBusiness = null; private BuilderLogic builder = null; private AccessController accessController = null; public CaseUserImpl(User user, ProcessInstanceW processInstanceW) { this.user = user; this.processInstanceW = processInstanceW; } protected CasesBPMDAO getCasesDAO() { if (this.casesBPMDAO == null) { ELUtil.getInstance().autowire(this); } return casesBPMDAO; } protected ICObjectInstanceHome getICObjectInstanceHome() { if (this.icObjectInstanceHome != null) { return this.icObjectInstanceHome; } try { this.icObjectInstanceHome = (ICObjectInstanceHome) IDOLookup .getHome(ICObjectInstance.class); } catch (IDOLookupException e) { LOGGER.log(Level.WARNING, "Unable to get " + ICObjectInstanceHome.class.getName() + " cause of: ", e); } return this.icObjectInstanceHome; } protected CasesBusiness getCasesBusiness(IWApplicationContext iwac) { if (this.casesBusiness != null) { return this.casesBusiness; } try { this.casesBusiness = IBOLookup.getServiceInstance( iwac, CasesBusiness.class); } catch (IBOLookupException ile) { LOGGER.log(Level.WARNING, "Unable to get " + CasesBusiness.class.getName() + " cause of: ", ile); } return this.casesBusiness; } protected UserBusiness getUserBusiness(IWApplicationContext iwac) { if (this.userBusiness != null) { return this.userBusiness; } try { this.userBusiness = (UserBusiness) IBOLookup.getServiceInstance(iwac, UserBusiness.class); } catch (IBOLookupException ile) { throw new IBORuntimeException(ile); } return this.userBusiness; } protected BuilderLogic getBuilderLogic() { if (this.builder == null) { this.builder = BuilderLogic.getInstance(); } return this.builder; } protected AccessController getAccessController(IWApplicationContext iwac) { if (this.accessController == null && iwac != null) { this.accessController = iwac.getIWMainApplication().getAccessController(); } return this.accessController; } public User getUser() { return user; } /** * * if the user has login: if the user is handler -> link to opencases else * -> link to usercases else link to case view using this user as bpm user * (see participant invitation) * * @return */ public String getUrlToTheCase() { final IWApplicationContext iwac = IWMainApplication.getDefaultIWApplicationContext(); UserBusiness userBusiness = getUserBusiness(iwac); User user = getUser(); boolean userHasLogin; boolean checkCaseStatus = iwac.getApplicationSettings() .getBoolean(CHECK_CASE_STATUS, Boolean.FALSE); try { userHasLogin = userBusiness.hasUserLogin(user); } catch (RemoteException e) { throw new IBORuntimeException(e); } String fullUrl; if (userHasLogin) { if (getProcessInstanceW().hasRight(Right.processHandler, user)) { // handler, get link to opencases if (checkCaseStatus) { fullUrl = getOpenCasesUrl(iwac, user, getProcessInstanceW().getProcessInstanceId()); } else { fullUrl = getOpenCasesUrl(iwac, user); } } else { // not handler, get link to usercases fullUrl = getUserCasesUrl(iwac, user); } final URIUtil uriUtil = new URIUtil(fullUrl); uriUtil.setParameter(BPMUser.processInstanceIdParam, String.valueOf(getProcessInstanceW().getProcessInstanceId())); fullUrl = uriUtil.getUri(); } else { // hasn't login, get link to case view UserPersonalData upd = new UserPersonalData(); try { Email email = user.getUsersEmail(); if(email != null) { upd.setUserEmail(email.getEmailAddress()); } } catch (RemoteException e) { Logger.getLogger(getClass().getName()).log(Level.WARNING, "Exception while resolving user ("+user.getPrimaryKey()+") email"); } upd.setFullName(user.getName()); upd.setUserType(BPMUser.USER_TYPE_NATURAL); upd.setPersonalId(user.getPersonalID()); List<Role> roles = getBpmFactory().getRolesManager().getUserRoles(getProcessInstanceW().getProcessInstanceId(), user); if(roles != null && !roles.isEmpty()) { // here we could find the most permissive role of the user, or add all roles for the bpm user (better way) Role role = roles.iterator().next(); BPMUser bpmUser = getBpmUserFactory().createBPMUser(upd, role, getProcessInstanceW().getProcessInstanceId()); fullUrl = getAssetsUrl(iwac, user); final URIUtil uriUtil = new URIUtil(fullUrl); List<URIParam> params = bpmUser.getParamsForBPMUserLink(); for (URIParam param : params) { uriUtil.setParameter(param.getParamName(), param.getParamValue()); } fullUrl = uriUtil.getUri(); } else { fullUrl = null; Logger.getLogger(getClass().getName()).log(Level.WARNING, "No roles resolved for the user with id="+user.getPrimaryKey()+" and process instance id = "+getProcessInstanceW().getProcessInstanceId()+", skipping creating url to the case"); } } return fullUrl; } protected List<String> getStatusesToShow(BuilderLogic builder, String pageKey, String instanceId) { String show = getProperty(builder, pageKey, instanceId, ":method:1:implied:void:setCaseStatusesToShow:java.lang.String:"); return StringUtil.isEmpty(show) ? null : new ArrayList<String>( Arrays.asList(show.split(CoreConstants.COMMA))); } protected String getProperty(BuilderLogic builder, String pageKey, String instanceId, String property) { return builder.getProperty(pageKey, instanceId, property); } /** * * @param instance is component, which link should be found; * @param iwac is application context, where to search for links, not * <code>null</code>; * @param user, who should have access rights to required link, not * <code>null</code>; * @return {@link URL} of page by {@link ICObjectInstance}, accessible * for given {@link User} or <code>null</code> on failure; * @author <a href="mailto:martynas@idega.is">Martynas Stakė</a> */ protected String getCaseURL(ICObjectInstance instance, IWApplicationContext iwac, User user) { if (instance == null || iwac == null || user == null) return null; String uniqueId = instance.getUniqueId(); if (StringUtil.isEmpty(uniqueId)) return null; String instanceId = ICObjectBusiness.UUID_PREFIX.concat(uniqueId); ICPage page = getBuilderLogic().findPageForModule(iwac, instanceId); if (page == null || page.getDeleted()) return null; if(!getAccessController(iwac).hasViewPermissionForPageKey( page.getPageKey(), CoreUtil.getIWContext())){ return null; } String pageKey = page.getId(); List<String> statusesToShow = getStatusesToShow(getBuilderLogic(), pageKey, instanceId); if (ListUtil.isEmpty(statusesToShow)) { return null; } Case theCase = getCase(getProcessInstanceW().getProcessInstanceId()); if (theCase == null || !statusesToShow.contains(theCase.getStatus())) { return null; } String uri = page.getDefaultPageURI(); if (!uri.startsWith(CoreConstants.PAGES_URI_PREFIX)) uri = CoreConstants.PAGES_URI_PREFIX + uri; URIUtil uriUtil = new URIUtil(uri); uriUtil.setParameter( LoginBusinessBean.PARAM_LOGIN_BY_UNIQUE_ID, user.getUniqueId()); uriUtil.setParameter( LoginBusinessBean.LoginStateParameter, LoginBusinessBean.LOGIN_EVENT_LOGIN); return iwac.getIWMainApplication() .getTranslatedURIWithContext(uriUtil.getUri()); } /** * * <p>Searches for links to visual components, where required * {@link ProcessInstance} can be viewed.</p> * @param classType is type of cases should be viewed, for example: * <li>OpenCases</li> * <li>ClosedCases</li> * <li>MyCases</li> * <li>PublicCases</li> * <li>UserCases</li> * <li>HandlerCases</li> * @param iwac is application context, where to search for links, not * <code>null</code>; * @param user, who should be available to see the {@link ProcessInstance}, * not <code>null</code>; * @param processInstanceId is id of {@link ProcessInstance}, which should * be viewed, not <code>null</code>; * @return {@link List} of accessible links to {@link User} or * {@link Collections#emptyList()}; * @author <a href="mailto:martynas@idega.is">Martynas Stakė</a> */ public ArrayList<String> getCasesURLs( Class<? extends CaseBlock> classType, IWApplicationContext iwac, User user, Long processInstanceId) { if (classType == null || iwac == null || user == null || processInstanceId == null) { return null; } Collection<ICObjectInstance> instances = null; try { instances = getICObjectInstanceHome().getByClassName(classType); } catch (FinderException e) { java.util.logging.Logger.getLogger(getClass().getName()).log( Level.WARNING, "Unable to find " + classType + " component: ", e); } if (ListUtil.isEmpty(instances)) { return null; } ArrayList<String> urls = new ArrayList<String>(instances.size()); for (ICObjectInstance instance: instances) { String url = getCaseURL(instance, iwac, user); if (!StringUtil.isEmpty(url)) { urls.add(url); } } return urls; } /** * * <p>Searches for links to visual components, where required * {@link ProcessInstance} can be viewed. Searches links for: * <li>OpenCases</li> * <li>ClosedCases</li> * <li>MyCases</li> * <li>PublicCases</li> * <li>UserCases</li> * <li>HandlerCases</li></p> * @param iwac is application context, where to search for links, not * <code>null</code>; * @param user, who should be available to see the {@link ProcessInstance}, * not <code>null</code>; * @param processInstanceId is id of {@link ProcessInstance}, which should * be viewed, not <code>null</code>; * @return {@link List} of accessible links to {@link User} or * {@link Collections#emptyList()}; * @author <a href="mailto:martynas@idega.com">Martynas Stakė</a> */ public ArrayList<String> getCasesURLs( IWApplicationContext iwac, User user, Long processInstanceId) { if (iwac == null || user == null || processInstanceId == null) { return new ArrayList<String>(0); } List<Class<? extends CaseBlock>> classes = new ArrayList<Class<? extends CaseBlock>>(); classes.add(OpenCases.class); classes.add(ClosedCases.class); classes.add(MyCases.class); classes.add(PublicCases.class); classes.add(UserCases.class); classes.add(HandlerCases.class); ArrayList<String> urls = new ArrayList<String>(); for (Class<? extends CaseBlock> theClass : classes) { ArrayList<String> urlsForClass = getCasesURLs( theClass, iwac, user, processInstanceId); if (ListUtil.isEmpty(urlsForClass)) { continue; } urls.addAll(urlsForClass); } return urls; } /** * * <p>Searches {@link OpenCases} page in pages tree of application, * accessible for current {@link User}.</p> * @param iwac is current application context, where to search; * @param user, who should be able to access page, not <code>null</code>; * @param processInstanceId is id of {@link ProcessInstance}, which should * be accessed; * @return url to {@link OpenCases} page or <code>null</code> on failure; * @author <a href="mailto:martynas@idega.com">Martynas Stakė</a> */ protected String getOpenCasesUrl(IWApplicationContext iwac, User user, Long processInstanceId) { if (user == null) { return null; } ArrayList<String> urls = getCasesURLs( OpenCases.class, iwac, user, processInstanceId); if (!ListUtil.isEmpty(urls)) { return urls.iterator().next(); } return getBuilderService(iwac).getFullPageUrlByPageType(user, OpenCases.pageType, true); } /** * * <p>Searches for {@link Case} by {@link ProcessInstance}.</p> * @param processInstanceId is {@link ProcessInstance#getId()} of * {@link Case} required, not <code>null</code>; * @return {@link Case} by {@link ProcessInstance} or <code>null</code> * on failure; * @author <a href="mailto:martynas@idega.com">Martynas Stakė</a> */ protected Case getCase(Long processInstanceId) { CaseProcInstBind bind = null; try { bind = getCasesDAO().getCaseProcInstBindByProcessInstanceId(processInstanceId); } catch(Exception e) { java.util.logging.Logger.getLogger(getClass().getName()).log( Level.WARNING, "Error getting case for process instance: " + processInstanceId); } if (bind == null) { return null; } try { return getCasesBusiness(IWMainApplication.getDefaultIWApplicationContext()).getCase(bind.getCaseId()); } catch(Exception e) { java.util.logging.Logger.getLogger(getClass().getName()).log( Level.WARNING, "Error getting case by id: " + bind.getCaseId(), e); } return null; } public ProcessInstanceW getProcessInstanceW() { return processInstanceW; } private String getAssetsUrl(IWApplicationContext iwac, User currentUser) { return getBuilderService(iwac).getFullPageUrlByPageType(currentUser, BPMUser.defaultAssetsViewPageType, true); } private String getOpenCasesUrl(IWApplicationContext iwac, User user) { return getBuilderService(iwac).getFullPageUrlByPageType(user, OpenCases.pageType, true); } private String getUserCasesUrl(IWApplicationContext iwac, User currentUser) { return getBuilderService(iwac).getFullPageUrlByPageType(currentUser, UserCases.pageType, true); } private BuilderService getBuilderService(IWApplicationContext iwc) { try { return BuilderServiceFactory.getBuilderService(iwc); } catch (RemoteException e) { throw new IBORuntimeException(e); } } public void setBpmUserFactory(BPMUserFactory bpmUserFactory) { this.bpmUserFactory = bpmUserFactory; } BPMUserFactory getBpmUserFactory() { return bpmUserFactory; } BPMFactory getBpmFactory() { return bpmFactory; } public void setBpmFactory(BPMFactory bpmFactory) { this.bpmFactory = bpmFactory; } }