1 package org.argeo.connect.e4.resources.parts;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import javax.annotation.PostConstruct;
7 import javax.annotation.PreDestroy;
8 import javax.inject.Inject;
9 import javax.jcr.Node;
10 import javax.jcr.NodeIterator;
11 import javax.jcr.Property;
12 import javax.jcr.Repository;
13 import javax.jcr.RepositoryException;
14 import javax.jcr.Session;
15 import javax.jcr.nodetype.NodeType;
16 import javax.jcr.query.Query;
17
18 import org.argeo.cms.auth.CurrentUser;
19 import org.argeo.connect.ConnectException;
20 import org.argeo.connect.resources.ResourcesNames;
21 import org.argeo.connect.resources.ResourcesRole;
22 import org.argeo.connect.resources.ResourcesService;
23 import org.argeo.connect.ui.ConnectColumnDefinition;
24 import org.argeo.connect.ui.ConnectUiSnippets;
25 import org.argeo.connect.ui.Refreshable;
26 import org.argeo.connect.ui.SystemWorkbenchService;
27 import org.argeo.connect.ui.parts.AskTitleDescriptionDialog;
28 import org.argeo.connect.ui.util.JcrHtmlLabelProvider;
29 import org.argeo.connect.ui.util.JcrViewerDClickListener;
30 import org.argeo.connect.ui.util.VirtualJcrTableViewer;
31 import org.argeo.connect.util.ConnectJcrUtils;
32 import org.argeo.connect.util.XPathUtils;
33 import org.argeo.eclipse.ui.EclipseUiUtils;
34 import org.argeo.jcr.JcrUtils;
35 import org.eclipse.e4.ui.di.Focus;
36 import org.eclipse.jface.dialogs.Dialog;
37 import org.eclipse.jface.dialogs.MessageDialog;
38 import org.eclipse.jface.viewers.ColumnLabelProvider;
39 import org.eclipse.jface.viewers.TableViewer;
40 import org.eclipse.jface.wizard.Wizard;
41 import org.eclipse.jface.wizard.WizardDialog;
42 import org.eclipse.rap.rwt.RWT;
43 import org.eclipse.swt.SWT;
44 import org.eclipse.swt.events.ModifyEvent;
45 import org.eclipse.swt.events.ModifyListener;
46 import org.eclipse.swt.events.SelectionAdapter;
47 import org.eclipse.swt.events.SelectionEvent;
48 import org.eclipse.swt.layout.GridLayout;
49 import org.eclipse.swt.widgets.Button;
50 import org.eclipse.swt.widgets.Composite;
51 import org.eclipse.swt.widgets.Text;
52
53
54
55
56
57 public class SearchTagsEditor implements Refreshable {
58
59
60
61
62 @Inject
63 private Repository repository;
64 @Inject
65 private ResourcesService resourcesService;
66 @Inject
67 private SystemWorkbenchService systemWorkbenchService;
68
69
70 private Session session;
71 private Node tagParent;
72 private String tagId;
73 private String tagInstanceType;
74 private String propertyName;
75
76
77 private List<ConnectColumnDefinition> colDefs = new ArrayList<ConnectColumnDefinition>();
78 private TableViewer tableViewer;
79 private Text filterTxt;
80
81 public void init() {
82
83
84
85
86
87 tagInstanceType = null;
88 session = ConnectJcrUtils.login(repository);
89 tagParent = resourcesService.getTagLikeResourceParent(session, tagInstanceType);
90 tagId = ConnectJcrUtils.get(tagParent, ResourcesNames.RESOURCES_TAG_ID);
91
92 colDefs.add(new ConnectColumnDefinition("Title", new JcrHtmlLabelProvider(Property.JCR_TITLE), 300));
93 colDefs.add(new ConnectColumnDefinition("Member count", new CountMemberLP(), 85));
94 if (canEdit())
95 colDefs.add(new ConnectColumnDefinition("", new EditLabelProvider(), 80));
96 }
97
98
99 @PostConstruct
100 public void createPartControl(Composite parent) {
101 init();
102 parent.setLayout(EclipseUiUtils.noSpaceGridLayout());
103
104 Composite searchCmp = new Composite(parent, SWT.NO_FOCUS);
105 populateSearchPanel(searchCmp);
106 searchCmp.setLayoutData(EclipseUiUtils.fillWidth());
107
108
109 Composite tableCmp = new Composite(parent, SWT.NO_FOCUS);
110 createListPart(tableCmp);
111 tableCmp.setLayoutData(EclipseUiUtils.fillAll());
112 refreshStaticFilteredList();
113 }
114
115
116 protected void populateSearchPanel(Composite parent) {
117 parent.setLayout(new GridLayout(2, false));
118 filterTxt = new Text(parent, SWT.BORDER | SWT.SEARCH | SWT.ICON_SEARCH | SWT.ICON_CANCEL);
119 filterTxt.setLayoutData(EclipseUiUtils.fillWidth());
120 filterTxt.addModifyListener(new ModifyListener() {
121 private static final long serialVersionUID = 5003010530960334977L;
122
123 public void modifyText(ModifyEvent event) {
124 refreshStaticFilteredList();
125 }
126 });
127
128 Button addBtn = new Button(parent, SWT.PUSH);
129 addBtn.setText("Create new...");
130 addBtn.addSelectionListener(new SelectionAdapter() {
131 private static final long serialVersionUID = -1990521824772413097L;
132
133 @Override
134 public void widgetSelected(SelectionEvent e) {
135 AskTitleDescriptionDialog dialog = new AskTitleDescriptionDialog(e.display.getActiveShell(), "Create");
136 if (Dialog.OK == dialog.open()) {
137 try {
138 Node tag = resourcesService.registerTag(session, tagId, dialog.getTitle());
139 String desc = dialog.getDescription();
140 if (EclipseUiUtils.notEmpty(desc))
141 tag.setProperty(Property.JCR_DESCRIPTION, desc);
142 if (tag.isNodeType(NodeType.MIX_VERSIONABLE))
143 ConnectJcrUtils.saveAndPublish(tag, true);
144 else
145 session.save();
146 refreshStaticFilteredList();
147 } catch (RepositoryException re) {
148 throw new ConnectException("Unable to create new " + propertyName, re);
149 }
150 }
151 }
152 });
153 }
154
155 protected void createListPart(Composite parent) {
156 parent.setLayout(new GridLayout());
157 VirtualJcrTableViewer tableCmp = new VirtualJcrTableViewer(parent, SWT.MULTI, colDefs);
158 tableViewer = tableCmp.getTableViewer();
159 tableCmp.setLayoutData(EclipseUiUtils.fillAll());
160 tableViewer.addDoubleClickListener(new JcrViewerDClickListener());
161 tableViewer.getTable().addSelectionListener(new HtmlRwtAdapter());
162 }
163
164
165 protected void refreshStaticFilteredList() {
166 try {
167 String queryStr = XPathUtils.descendantFrom(tagParent.getPath()) + "//element(*, " + tagInstanceType + ")";
168 String attrQuery = XPathUtils.getFreeTextConstraint(filterTxt.getText());
169 if (EclipseUiUtils.notEmpty(attrQuery))
170 queryStr += "[" + attrQuery + "]";
171
172 queryStr += " order by @" + Property.JCR_TITLE;
173 Query query = XPathUtils.createQuery(session, queryStr);
174 NodeIterator nit = query.execute().getNodes();
175 Node[] nodes = ConnectJcrUtils.nodeIteratorToArray(nit);
176 setViewerInput(nodes);
177 } catch (RepositoryException e) {
178 throw new ConnectException("Unable to list " + tagInstanceType, e);
179 }
180 }
181
182
183 protected void setViewerInput(Object[] elements) {
184 tableViewer.setInput(elements);
185
186 tableViewer.setItemCount(elements.length);
187 tableViewer.refresh();
188 }
189
190 protected class CountMemberLP extends ColumnLabelProvider {
191 private static final long serialVersionUID = 1L;
192
193 @Override
194 public String getText(Object element) {
195 Node currNode = ConnectJcrUtils.getNodeFromElement(element, null);
196 long count = resourcesService.countMembers(currNode);
197 return "" + count;
198 }
199 }
200
201 protected class EditLabelProvider extends ColumnLabelProvider {
202 private static final long serialVersionUID = 1L;
203
204 @Override
205 public String getText(Object element) {
206 Node currNode = ConnectJcrUtils.getNodeFromElement(element, null);
207 try {
208 String jcrId = currNode.getIdentifier();
209 StringBuilder builder = new StringBuilder();
210 if (canEdit())
211 builder.append(ConnectUiSnippets.getRWTLink("edit/" + jcrId, "Edit")).append(" ");
212
213
214
215 if (canDelete(currNode))
216 builder.append(ConnectUiSnippets.getRWTLink("delete/" + jcrId, "Delete"));
217 return builder.toString();
218 } catch (RepositoryException re) {
219 throw new ConnectException("Unable to create edit/remove link for " + currNode, re);
220 }
221 }
222 }
223
224 private boolean canEdit() {
225 return CurrentUser.isInRole(ResourcesRole.editor.dn());
226 }
227
228 private boolean canDelete(Node currNode) {
229 long currCount = resourcesService.countMembers(currNode);
230 return canEdit() && currCount == 0;
231 }
232
233 private class HtmlRwtAdapter extends SelectionAdapter {
234 private static final long serialVersionUID = 1L;
235
236 public void widgetSelected(SelectionEvent event) {
237 if (event.detail == RWT.HYPERLINK) {
238 String string = event.text;
239 String[] token = string.split("/");
240 try {
241 Node node = session.getNodeByIdentifier(token[1]);
242
243 if ("edit".equals(token[0])) {
244 Wizard wizard = new EditTagWizard(resourcesService, systemWorkbenchService, node, tagId,
245 propertyName);
246 WizardDialog dialog = new WizardDialog(event.display.getActiveShell(), wizard);
247 int result = dialog.open();
248 if (result == WizardDialog.OK) {
249 refreshStaticFilteredList();
250 }
251 } else {
252 if (canDelete(node)) {
253 String msg = "Are you sure you want to delete \""
254 + ConnectJcrUtils.get(node, Property.JCR_TITLE) + "\" ?";
255 if (MessageDialog.openConfirm(event.display.getActiveShell(), "Confirm deletion", msg)) {
256 ConnectJcrUtils.checkCOStatusBeforeUpdate(node);
257 session.removeItem(node.getPath());
258 session.save();
259 refreshStaticFilteredList();
260 }
261 }
262 }
263 } catch (RepositoryException re) {
264 throw new ConnectException("unable to retrieve Node with ID " + token[1], re);
265 }
266 }
267 }
268 }
269
270 @Override
271 public void forceRefresh(Object object) {
272 refreshStaticFilteredList();
273 }
274
275 @Focus
276 public void setFocus() {
277 filterTxt.setFocus();
278 }
279
280 @PreDestroy
281 public void dispose() {
282 JcrUtils.logoutQuietly(session);
283 }
284
285
286
287
288
289
290
291
292
293
294
295
296
297 }