View Javadoc
1   package org.argeo.people.e4.parts;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.Comparator;
6   import java.util.HashMap;
7   import java.util.List;
8   import java.util.Map;
9   
10  import javax.jcr.Node;
11  import javax.jcr.NodeIterator;
12  import javax.jcr.RepositoryException;
13  
14  import org.argeo.cms.ui.eclipse.forms.FormToolkit;
15  import org.argeo.connect.resources.ResourcesService;
16  import org.argeo.connect.ui.ConnectEditor;
17  import org.argeo.connect.ui.ConnectImages;
18  import org.argeo.connect.ui.ConnectUiConstants;
19  import org.argeo.connect.ui.ConnectUiUtils;
20  import org.argeo.connect.ui.SystemWorkbenchService;
21  import org.argeo.connect.ui.parts.AbstractPanelFormPart;
22  import org.argeo.connect.ui.util.BasicNodeListContentProvider;
23  import org.argeo.connect.ui.util.BooleanEditingSupport;
24  import org.argeo.connect.ui.util.HtmlListRwtAdapter;
25  import org.argeo.connect.ui.util.LazyCTabControl;
26  import org.argeo.connect.util.ConnectJcrUtils;
27  import org.argeo.eclipse.ui.EclipseUiUtils;
28  import org.argeo.eclipse.ui.utils.ViewerUtils;
29  import org.argeo.people.PeopleException;
30  import org.argeo.people.PeopleNames;
31  import org.argeo.people.PeopleService;
32  import org.argeo.people.PeopleTypes;
33  import org.argeo.people.e4.handlers.EditJob;
34  import org.argeo.people.ui.providers.BooleanFlagLabelProvider;
35  import org.argeo.people.ui.providers.OrgOverviewLabelProvider;
36  import org.argeo.people.ui.providers.PersonOverviewLabelProvider;
37  import org.argeo.people.ui.providers.RoleListLabelProvider;
38  import org.argeo.people.util.PeopleJcrUtils;
39  import org.eclipse.jface.layout.TableColumnLayout;
40  import org.eclipse.jface.viewers.ColumnLabelProvider;
41  import org.eclipse.jface.viewers.ColumnWeightData;
42  import org.eclipse.jface.viewers.TableViewer;
43  import org.eclipse.jface.viewers.TableViewerColumn;
44  import org.eclipse.swt.SWT;
45  import org.eclipse.swt.events.SelectionAdapter;
46  import org.eclipse.swt.events.SelectionEvent;
47  import org.eclipse.swt.layout.GridData;
48  import org.eclipse.swt.layout.GridLayout;
49  import org.eclipse.swt.widgets.Button;
50  import org.eclipse.swt.widgets.Composite;
51  
52  /**
53   * A composite to include in a form and that displays an editable list of jobs
54   * or employees
55   */
56  public class JobListCTab extends LazyCTabControl {
57  	private static final long serialVersionUID = -4736848221960630767L;
58  
59  	// Context
60  	private final ResourcesService resourcesService;
61  	private final PeopleService peopleService;
62  	private final SystemWorkbenchService systemWorkbenchService;
63  	private final ConnectEditor editor;
64  	private final FormToolkit toolkit;
65  	private final Node entity;
66  	private final boolean isBackward;
67  
68  	// UI Objects
69  	private MyFormPart myFormPart;
70  
71  	/**
72  	 * 
73  	 * @param parent
74  	 * @param style
75  	 * @param editor
76  	 * @param resourcesService
77  	 * @param peopleService
78  	 * @param systemWorkbenchService
79  	 * @param entity
80  	 */
81  	public JobListCTab(Composite parent, int style, ConnectEditor editor, ResourcesService resourcesService,
82  			PeopleService peopleService, SystemWorkbenchService systemWorkbenchService, Node entity) {
83  		super(parent, style);
84  		toolkit = editor.getFormToolkit();
85  		this.resourcesService = resourcesService;
86  		this.peopleService = peopleService;
87  		this.systemWorkbenchService = systemWorkbenchService;
88  		this.entity = entity;
89  		this.editor = editor;
90  		// Participations are stored in the projects.
91  		isBackward = ConnectJcrUtils.isNodeType(entity, PeopleTypes.PEOPLE_ORG);
92  	}
93  
94  	@Override
95  	public void refreshPartControl() {
96  		myFormPart.refresh();
97  		layout(true, true);
98  	}
99  
100 	@Override
101 	public void createPartControl(Composite parent) {
102 		myFormPart = new MyFormPart(this);
103 		myFormPart.initialize(editor.getManagedForm());
104 		editor.getManagedForm().addPart(myFormPart);
105 	}
106 
107 	private class MyFormPart extends AbstractPanelFormPart {
108 		private TableViewer itemViewer;
109 
110 		public MyFormPart(Composite parent) {
111 			super(parent, editor, entity);
112 		}
113 
114 		protected void reCreateChildComposite(Composite panel, Node entity) {
115 			// Add button if needed
116 			Button addBtn = null;
117 			if (isEditing()) {
118 				panel.setLayout(new GridLayout());
119 				addBtn = toolkit.createButton(panel, "", SWT.PUSH);
120 				configureAddBtn(addBtn);
121 			} else {
122 				panel.setLayout(EclipseUiUtils.noSpaceGridLayout());
123 			}
124 
125 			// Item list
126 			Composite tableComp = toolkit.createComposite(panel);
127 			itemViewer = createItemViewer(tableComp);
128 			tableComp.setLayoutData(EclipseUiUtils.fillAll());
129 			refreshContent(panel, entity);
130 		}
131 
132 		protected void refreshContent(Composite parent, Node entity) {
133 			if (isBackward) {
134 				List<Node> employees = peopleService.getRelatedEntities(entity, PeopleTypes.PEOPLE_JOB,
135 						PeopleTypes.PEOPLE_PERSON);
136 				Collections.sort(employees, lastNameFirstNamePersonComparator);
137 				itemViewer.setInput(employees);
138 			} else {
139 				try {
140 					List<Node> jobs = new ArrayList<Node>();
141 					if (!entity.hasNode(PeopleNames.PEOPLE_JOBS))
142 						return; // No member to display
143 					NodeIterator ni = entity.getNode(PeopleNames.PEOPLE_JOBS).getNodes();
144 					while (ni.hasNext()) {
145 						// Check relevant nodeType
146 						Node currNode = ni.nextNode();
147 						if (currNode.isNodeType(PeopleTypes.PEOPLE_JOB)) {
148 							jobs.add(currNode);
149 						}
150 					}
151 					itemViewer.setInput(jobs);
152 				} catch (RepositoryException re) {
153 					throw new PeopleException("Cannot refresh person job list for " + entity, re);
154 				}
155 			}
156 		}
157 	}
158 
159 	private TableViewer createItemViewer(Composite parent) {
160 		TableViewer viewer = new TableViewer(parent, SWT.V_SCROLL);
161 		ConnectUiUtils.setTableDefaultStyle(viewer, 60);
162 		TableColumnLayout tableColumnLayout = new TableColumnLayout();
163 		TableViewerColumn col;
164 
165 		// Primary job for persons only
166 		if (!isBackward) {
167 			col = ViewerUtils.createTableViewerColumn(viewer, "", SWT.CENTER, 25);
168 			PrimaryEditingSupport editingSupport = new PrimaryEditingSupport(viewer, PeopleNames.PEOPLE_IS_PRIMARY);
169 			col.setEditingSupport(editingSupport);
170 			col.setLabelProvider(new BooleanFlagLabelProvider(PeopleNames.PEOPLE_IS_PRIMARY, ConnectImages.PRIMARY,
171 					ConnectImages.PRIMARY_NOT));
172 			tableColumnLayout.setColumnData(col.getColumn(), new ColumnWeightData(0, 26, true));
173 		}
174 
175 		// Role
176 		col = ViewerUtils.createTableViewerColumn(viewer, "", SWT.LEFT, 150);
177 		col.setLabelProvider(new RoleListLabelProvider());
178 		tableColumnLayout.setColumnData(col.getColumn(), new ColumnWeightData(80, 20, true));
179 
180 		// Linked entity
181 		col = ViewerUtils.createTableViewerColumn(viewer, "", SWT.LEFT, 300);
182 		tableColumnLayout.setColumnData(col.getColumn(), new ColumnWeightData(200, 80, true));
183 		if (isBackward)
184 			col.setLabelProvider(new PersonOverviewLabelProvider(ConnectUiConstants.LIST_TYPE_MEDIUM, resourcesService,
185 					peopleService, systemWorkbenchService));
186 		else
187 			col.setLabelProvider(
188 					new OrgOverviewLabelProvider(true, resourcesService, peopleService, systemWorkbenchService));
189 
190 		// Edit & Remove links
191 		if (editor.isEditing()) {
192 			col = ViewerUtils.createTableViewerColumn(viewer, "Edit/Remove links", SWT.NONE, 60);
193 			tableColumnLayout.setColumnData(col.getColumn(), new ColumnWeightData(40, 40, true));
194 			col.setLabelProvider(new ColumnLabelProvider() {
195 				private static final long serialVersionUID = 1L;
196 
197 				@Override
198 				public String getText(Object element) {
199 					Node link = (Node) element;
200 					return PeopleRapSnippets.getEditJobSnippetForLists(link, isBackward) + " <br />"
201 							+ PeopleRapSnippets.getRemoveReferenceSnippetForLists(link);
202 				}
203 			});
204 		}
205 
206 		// Providers and listeners
207 		viewer.setContentProvider(new BasicNodeListContentProvider());
208 		viewer.addDoubleClickListener(new ListDoubleClickListener());
209 		viewer.getTable().addSelectionListener(new HtmlListRwtAdapter(systemWorkbenchService));
210 
211 		// Important don't forget this.
212 		parent.setLayout(tableColumnLayout);
213 		return viewer;
214 	}
215 
216 	private void configureAddBtn(Button button) {
217 		String tooltip = "", text = "";
218 		if (isBackward) {
219 			text = "Add an employee";
220 			tooltip = "Register the position of a person in this organisation";
221 		} else {
222 			text = "Add job";
223 			tooltip = "Register a position in an organisation";
224 		}
225 
226 		button.setToolTipText(tooltip);
227 		button.setText(text);
228 
229 		button.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
230 		button.addSelectionListener(new SelectionAdapter() {
231 			private static final long serialVersionUID = 1L;
232 
233 			@Override
234 			public void widgetSelected(SelectionEvent e) {
235 				Map<String, String> params = new HashMap<String, String>();
236 				params.put(EditJob.PARAM_RELEVANT_NODE_JCR_ID, ConnectJcrUtils.getIdentifier(entity));
237 				systemWorkbenchService.callCommand(EditJob.ID, params);
238 				// CommandUtils.callCommand(EditJob.ID, params);
239 			}
240 		});
241 	}
242 
243 	private class ListDoubleClickListener extends PeopleDoubleClickAdapter {
244 		@Override
245 		protected void processDoubleClick(Object obj) {
246 			if (obj instanceof Node) {
247 				Node link = (Node) obj;
248 				Node toOpen;
249 				if (isBackward) {
250 					toOpen = ConnectJcrUtils.getParent(ConnectJcrUtils.getParent(link));
251 				} else {
252 					toOpen = peopleService.getEntityByUid(ConnectJcrUtils.getSession(entity), null,
253 							ConnectJcrUtils.get(link, PeopleNames.PEOPLE_REF_UID));
254 				}
255 				// CommandUtils.callCommand(systemWorkbenchService.getOpenEntityEditorCmdId(),
256 				// ConnectEditor.PARAM_JCR_ID, ConnectJcrUtils.getIdentifier(toOpen));
257 				systemWorkbenchService.openEntityEditor(toOpen);
258 			}
259 		}
260 	}
261 
262 	private class PrimaryEditingSupport extends BooleanEditingSupport {
263 		private static final long serialVersionUID = 1L;
264 
265 		public PrimaryEditingSupport(TableViewer viewer, String propertyName) {
266 			super(viewer, propertyName);
267 		}
268 
269 		@Override
270 		protected boolean canEdit(Object element) {
271 			return editor.isEditing();
272 		}
273 
274 		@Override
275 		protected void setValue(Object element, Object value) {
276 			Node currNode = (Node) element;
277 			if (((Boolean) value).booleanValue()
278 					&& PeopleJcrUtils.markAsPrimary(resourcesService, peopleService, entity, currNode)) {
279 				myFormPart.refresh();
280 				myFormPart.markDirty();
281 			}
282 		}
283 	}
284 
285 	private static Comparator<Node> lastNameFirstNamePersonComparator = new Comparator<Node>() {
286 
287 		public int compare(Node node1, Node node2) {
288 			try {
289 				int rc = 0;
290 				// We have a job, we want to compare corresponding parent person
291 				if (node1 != null)
292 					node1 = node1.getParent().getParent();
293 				if (node2 != null)
294 					node2 = node2.getParent().getParent();
295 				String lastName1 = ConnectJcrUtils.get(node1, PeopleNames.PEOPLE_LAST_NAME).toLowerCase();
296 				String lastName2 = ConnectJcrUtils.get(node2, PeopleNames.PEOPLE_LAST_NAME).toLowerCase();
297 				String firstName1 = ConnectJcrUtils.get(node1, PeopleNames.PEOPLE_FIRST_NAME).toLowerCase();
298 				String firstName2 = ConnectJcrUtils.get(node2, PeopleNames.PEOPLE_FIRST_NAME).toLowerCase();
299 				rc = lastName1.compareTo(lastName2);
300 				if (rc == 0)
301 					rc = firstName1.compareTo(firstName2);
302 				return rc;
303 			} catch (RepositoryException e) {
304 				throw new PeopleException("Unable to compare " + node1 + " with " + node2, e);
305 			}
306 		}
307 	};
308 
309 }