package org.nightlabs.jfire.issuetracking.ui.overview; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.jdo.FetchPlan; import javax.jdo.JDOHelper; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.nightlabs.base.ui.composite.XComboComposite; import org.nightlabs.base.ui.composite.XComposite; import org.nightlabs.base.ui.exceptionhandler.ExceptionHandlerRegistry; import org.nightlabs.base.ui.job.Job; import org.nightlabs.i18n.I18nText; import org.nightlabs.jdo.NLJDOHelper; import org.nightlabs.jdo.query.QueryEvent; import org.nightlabs.jdo.query.QueryProvider; import org.nightlabs.jdo.query.AbstractSearchQuery.FieldChangeCarrier; import org.nightlabs.jfire.base.JFireEjb3Factory; import org.nightlabs.jfire.base.login.ui.Login; import org.nightlabs.jfire.base.ui.search.AbstractQueryFilterComposite; import org.nightlabs.jfire.issue.IssueType; import org.nightlabs.jfire.issue.dao.IssueTypeDAO; import org.nightlabs.jfire.issue.query.IssueQuery; import org.nightlabs.jfire.issuetracking.ui.resource.Messages; import org.nightlabs.jfire.jbpm.JbpmManagerRemote; import org.nightlabs.jfire.jbpm.dao.StateDefinitionDAO; import org.nightlabs.jfire.jbpm.graph.def.ProcessDefinition; import org.nightlabs.jfire.jbpm.graph.def.StateDefinition; import org.nightlabs.jfire.jbpm.graph.def.StateDefinitionName; import org.nightlabs.jfire.jbpm.graph.def.id.ProcessDefinitionID; import org.nightlabs.jfire.jbpm.graph.def.id.StateDefinitionID; import org.nightlabs.progress.ProgressMonitor; /** * @author Chairat Kongarayawetchakun <!-- chairat [AT] nightlabs [DOT] de --> * */ public class IssueFilterCompositeStateRelated extends AbstractQueryFilterComposite<IssueQuery> { private String baseName = "org.nightlabs.jfire.issuetracking.ui.resource.messages"; //$NON-NLS-1$ private ClassLoader loader = IssueFilterCompositeStateRelated.class.getClassLoader(); private XComboComposite<ProcessDefinition> processDefinitionsCombo; private ILabelProvider processDefinitionLabelProvider = new LabelProvider() { @Override public String getText(Object element) { if (element instanceof DummyProcessDefinition) { DummyProcessDefinition dDefinition = (DummyProcessDefinition) element; return dDefinition.getName().getText(); } if (element instanceof ProcessDefinition) { ProcessDefinition processDefinition = (ProcessDefinition) element; return processDefinition.getProcessDefinitionID(); } return super.getText(element); } }; private DummyProcessDefinition ALL_PROCESS_DEFINITION = new DummyProcessDefinition(); private class DummyProcessDefinition extends ProcessDefinition { private class DummyProcessDefinitionName extends I18nText { protected Map<String, String> names = new HashMap<String, String>(); @Override protected String getFallBackValue(String languageID) { return "All"; //$NON-NLS-1$ } @Override protected Map<String, String> getI18nMap() { return names; } } private DummyProcessDefinitionName name; @SuppressWarnings("deprecation") public DummyProcessDefinition() { name = new DummyProcessDefinitionName(); name.readFromProperties(baseName, loader, "org.nightlabs.jfire.issuetracking.ui.overview.IssueFilterCompositeStateRelated.processDefinition.all"); //$NON-NLS-1$ } @Override public String getProcessDefinitionID() { return "All"; //$NON-NLS-1$ } public DummyProcessDefinitionName getName() { return name; } } private XComboComposite<StateDefinition> stateDefinitionsCombo; private ILabelProvider stateDefinitionLabelProvider = new LabelProvider() { @Override public String getText(Object element) { if (element instanceof StateDefinition) { StateDefinition stateDefinition = (StateDefinition) element; return (stateDefinition.getProcessDefinitionID() == null?"": stateDefinition.getProcessDefinitionID() + ":" ) + stateDefinition.getName().getText(); //$NON-NLS-1$ //$NON-NLS-2$ } return super.getText(element); } }; private DummyStateDefinition ALL_STATE_DEFINITION = new DummyStateDefinition(); private class DummyStateDefinition extends StateDefinition { @SuppressWarnings("deprecation") public DummyStateDefinition() { } @Override public StateDefinitionName getName() { StateDefinitionName stateDefinitionName = new StateDefinitionName(this); stateDefinitionName.readFromProperties(baseName, loader, "org.nightlabs.jfire.issuetracking.ui.overview.IssueFilterCompositeStateRelated.stateDefinition.all"); //$NON-NLS-1$ return stateDefinitionName; } } /** * @param parent * The parent to instantiate this filter into. * @param style * The style to apply. * @param layoutMode * The layout mode to use. See {@link XComposite.LayoutMode}. * @param layoutDataMode * The layout data mode to use. See {@link XComposite.LayoutDataMode}. * @param queryProvider * The queryProvider to use. It may be <code>null</code>, but the caller has to * ensure, that it is set before {@link #getQuery()} is called! */ public IssueFilterCompositeStateRelated(Composite parent, int style, LayoutMode layoutMode, LayoutDataMode layoutDataMode, QueryProvider<? super IssueQuery> queryProvider) { super(parent, style, layoutMode, layoutDataMode, queryProvider); createComposite(); } /** * @param parent * The this to instantiate this filter into. * @param style * The style to apply. * @param queryProvider * The queryProvider to use. It may be <code>null</code>, but the caller has to * ensure, that it is set before {@link #getQuery()} is called! */ public IssueFilterCompositeStateRelated(Composite parent, int style, QueryProvider<? super IssueQuery> queryProvider) { super(parent, style, queryProvider); createComposite(); } @Override public Class<IssueQuery> getQueryClass() { return IssueQuery.class; } @Override protected void createComposite() { this.setLayout(new GridLayout(3, false)); XComposite mainComposite = new XComposite(this, SWT.NONE, LayoutMode.TIGHT_WRAPPER, LayoutDataMode.GRID_DATA); mainComposite.getGridLayout().numColumns = 2; new Label(mainComposite, SWT.NONE).setText(Messages.getString("org.nightlabs.jfire.issuetracking.ui.overview.IssueFilterCompositeStateRelated.issueTypeLabel")); //$NON-NLS-1$ processDefinitionsCombo = new XComboComposite<ProcessDefinition>(mainComposite, SWT.NONE | SWT.READ_ONLY, stateDefinitionLabelProvider); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); processDefinitionsCombo.setLayoutData(gridData); processDefinitionsCombo.setLabelProvider(processDefinitionLabelProvider); processDefinitionsCombo.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent e) { stateDefinitionsCombo.selectElement(ALL_STATE_DEFINITION); stateDefinitionsComboSelected(); ProcessDefinition selectedProcessDefinition = processDefinitionsCombo.getSelectedElement(); boolean isSelectAll = selectedProcessDefinition.equals(ALL_PROCESS_DEFINITION); if (isSelectAll) { getQuery().setProcessDefinitionID(null); getQuery().setFieldEnabled(IssueQuery.FieldName.processDefinitionID, false); } else { getQuery().setProcessDefinitionID((ProcessDefinitionID) JDOHelper.getObjectId(selectedProcessDefinition)); getQuery().setFieldEnabled(IssueQuery.FieldName.processDefinitionID, true); } stateDefinitionsCombo.removeAll(); stateDefinitionsCombo.addElement(ALL_STATE_DEFINITION); stateDefinitionsCombo.selectElementByIndex(0); List<StateDefinition> stateDefinitionList = processDefinition2StateDefinitions.get(selectedProcessDefinition); if (selectedProcessDefinition.equals(ALL_PROCESS_DEFINITION)) { for (List<StateDefinition> l : processDefinition2StateDefinitions.values()) { stateDefinitionsCombo.addElements(l); } } else { stateDefinitionsCombo.addElements(stateDefinitionList); } } }); new Label(mainComposite, SWT.NONE).setText(Messages.getString("org.nightlabs.jfire.issuetracking.ui.overview.IssueFilterCompositeStateRelated.stateLabel")); //$NON-NLS-1$ stateDefinitionsCombo = new XComboComposite<StateDefinition>(mainComposite, SWT.NONE | SWT.READ_ONLY, stateDefinitionLabelProvider); gridData = new GridData(GridData.FILL_HORIZONTAL); stateDefinitionsCombo.setLayoutData(gridData); stateDefinitionsCombo.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent e) { stateDefinitionsComboSelected(); } }); loadProperties(); } private void stateDefinitionsComboSelected() { StateDefinition selectedStateDefinition = stateDefinitionsCombo.getSelectedElement(); boolean isSelectAll = selectedStateDefinition.equals(ALL_STATE_DEFINITION); if (isSelectAll) { getQuery().setJbpmNodeName(null); getQuery().setFieldEnabled(IssueQuery.FieldName.jbpmNodeName, false); } else { getQuery().setJbpmNodeName(selectedStateDefinition.getJbpmNodeName()); getQuery().setFieldEnabled(IssueQuery.FieldName.jbpmNodeName, true); } } @Override protected void updateUI(QueryEvent event, List<FieldChangeCarrier> changedFields) { for (FieldChangeCarrier changedField : event.getChangedFields()) { if (IssueQuery.FieldName.processDefinitionID.equals(changedField.getPropertyName())) { ProcessDefinitionID newProcessDefinitionID = (ProcessDefinitionID) changedField.getNewValue(); if (newProcessDefinitionID == null) { processDefinitionsCombo.setSelection(ALL_PROCESS_DEFINITION); } else { for (ProcessDefinition processDefinition : processDefinitionsCombo.getElements()) { if (processDefinition != ALL_PROCESS_DEFINITION) if (JDOHelper.getObjectId(processDefinition).equals(newProcessDefinitionID)) { processDefinitionsCombo.setSelection(processDefinition); this.selectedProcessDefinition = processDefinition; break; } } } } else if (getEnableFieldName(IssueQuery.FieldName.processDefinitionID).equals(changedField.getPropertyName())) { boolean isActive = (Boolean) changedField.getNewValue(); setSearchSectionActive(isActive); if (!isActive) { getQuery().setProcessDefinitionID(null); } } else if (IssueQuery.FieldName.jbpmNodeName.equals(changedField.getPropertyName())) { String newJbpmNodeName = (String) changedField.getNewValue(); if (newJbpmNodeName == null) { stateDefinitionsCombo.setSelection(ALL_STATE_DEFINITION); } else { for (StateDefinition stateDefinition : stateDefinitionsCombo.getElements()) { if (stateDefinition.getJbpmNodeName() != null && stateDefinition.getJbpmNodeName().equals(newJbpmNodeName)) { stateDefinitionsCombo.setSelection(stateDefinition); this.selectedStateDefinition = stateDefinition; break; } } } } else if (getEnableFieldName(IssueQuery.FieldName.jbpmNodeName).equals(changedField.getPropertyName())) { boolean isActive = (Boolean) changedField.getNewValue(); setSearchSectionActive(isActive); if (!isActive) { getQuery().setJbpmNodeName(null); } } } // for (FieldChangeCarrier changedField : event.getChangedFields()) } private static final Set<String> fieldNames; static { fieldNames = new HashSet<String>(1); fieldNames.add(IssueQuery.FieldName.jbpmNodeName); fieldNames.add(IssueQuery.FieldName.processDefinitionID); } @Override protected Set<String> getFieldNames() { return fieldNames; } /** * Group ID for storing active states in the query. */ public static final String FILTER_GROUP_ID = "IssueFilterCompositeStateRelated"; //$NON-NLS-1$ @Override protected String getGroupID() { return FILTER_GROUP_ID; } private Map<ProcessDefinition, List<StateDefinition>> processDefinition2StateDefinitions = new HashMap<ProcessDefinition, List<StateDefinition>>(); private ProcessDefinition selectedProcessDefinition; private StateDefinition selectedStateDefinition; private void loadProperties() { Job fillStateComboJob = new Job(Messages.getString("org.nightlabs.jfire.trade.ui.overview.StatableFilterComposite.loadProcessDefinitionsJob.name")) { //$NON-NLS-1$ @Override protected IStatus run(ProgressMonitor monitor) { try { JbpmManagerRemote jbpmManager = JFireEjb3Factory.getRemoteBean(JbpmManagerRemote.class, Login.getLogin().getInitialContextProperties()); String[] FETCH_GROUPS_ISSUE_TYPE = new String[] { FetchPlan.DEFAULT, IssueType.FETCH_GROUP_NAME, IssueType.FETCH_GROUP_PROCESS_DEFINITION }; IssueTypeDAO issueTypeDAO = IssueTypeDAO.sharedInstance(); Collection<IssueType> issueTypes = issueTypeDAO.getAllIssueTypes(FETCH_GROUPS_ISSUE_TYPE, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, monitor); String[] FETCH_GROUPS_STATE_DEFINITON = new String[] { FetchPlan.DEFAULT, StateDefinition.FETCH_GROUP_NAME }; for (IssueType issueType : issueTypes) { ProcessDefinition processDefinition = issueType.getProcessDefinition(); Set<StateDefinitionID> statedDefinitionIDs = jbpmManager.getStateDefinitionIDs(issueType.getProcessDefinition()); Collection<StateDefinition> stateDefinitions = StateDefinitionDAO.sharedInstance().getStateDefintions( statedDefinitionIDs, FETCH_GROUPS_STATE_DEFINITON, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, monitor); processDefinition2StateDefinitions.put(processDefinition, new ArrayList<StateDefinition>(stateDefinitions)); } Display.getDefault().syncExec(new Runnable() { public void run() { if (processDefinitionsCombo == null || processDefinitionsCombo.isDisposed() || stateDefinitionsCombo == null || stateDefinitionsCombo.isDisposed()) return; Set<ProcessDefinition> processDefinitions = processDefinition2StateDefinitions.keySet(); processDefinitionsCombo.addElement(ALL_PROCESS_DEFINITION); processDefinitionsCombo.addElements(processDefinitions); stateDefinitionsCombo.addElement(ALL_STATE_DEFINITION); if (!processDefinitions.isEmpty()) { ProcessDefinition firstProcessDefinition = processDefinitions.iterator().next(); List<StateDefinition> stateDefinitionList = processDefinition2StateDefinitions.get(firstProcessDefinition); stateDefinitionsCombo.addElements(stateDefinitionList); if (!stateDefinitionList.isEmpty()) { stateDefinitionsCombo.selectElementByIndex(0); } } processDefinitionsCombo.selectElementByIndex(0); if (selectedProcessDefinition != null) { processDefinitionsCombo.setSelection(selectedProcessDefinition); selectedProcessDefinition = null; } if (selectedStateDefinition != null) { stateDefinitionsCombo.setSelection(selectedStateDefinition); selectedStateDefinition = null; } } }); } catch (Exception e) { ExceptionHandlerRegistry.asyncHandleException(e); throw new RuntimeException(e); } return Status.OK_STATUS; } }; fillStateComboJob.schedule(); } }