1 package org.argeo.connect.e4.resources.parts;
2
3 import java.util.ArrayList;
4
5 import javax.jcr.Node;
6 import javax.jcr.Property;
7 import javax.jcr.PropertyType;
8 import javax.jcr.Repository;
9 import javax.jcr.RepositoryException;
10 import javax.jcr.Session;
11 import javax.jcr.nodetype.NodeType;
12 import javax.jcr.query.QueryManager;
13 import javax.jcr.query.QueryResult;
14 import javax.jcr.query.Row;
15 import javax.jcr.query.qom.Constraint;
16 import javax.jcr.query.qom.DynamicOperand;
17 import javax.jcr.query.qom.Ordering;
18 import javax.jcr.query.qom.QueryObjectModel;
19 import javax.jcr.query.qom.QueryObjectModelConstants;
20 import javax.jcr.query.qom.QueryObjectModelFactory;
21 import javax.jcr.query.qom.Selector;
22 import javax.jcr.query.qom.StaticOperand;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.argeo.cms.e4.PrivilegedJob;
27 import org.argeo.connect.ConnectException;
28 import org.argeo.connect.resources.ResourcesNames;
29 import org.argeo.connect.resources.ResourcesService;
30 import org.argeo.connect.ui.ConnectColumnDefinition;
31 import org.argeo.connect.ui.ConnectUiUtils;
32 import org.argeo.connect.ui.SystemWorkbenchService;
33 import org.argeo.connect.ui.util.TitleIconRowLP;
34 import org.argeo.connect.ui.util.VirtualJcrTableViewer;
35 import org.argeo.connect.util.ConnectJcrUtils;
36 import org.argeo.eclipse.ui.EclipseJcrMonitor;
37 import org.argeo.eclipse.ui.EclipseUiUtils;
38 import org.argeo.jcr.JcrMonitor;
39 import org.argeo.jcr.JcrUtils;
40 import org.eclipse.core.runtime.IProgressMonitor;
41 import org.eclipse.core.runtime.IStatus;
42 import org.eclipse.core.runtime.Status;
43 import org.eclipse.jface.dialogs.MessageDialog;
44 import org.eclipse.jface.viewers.ILazyContentProvider;
45 import org.eclipse.jface.viewers.TableViewer;
46 import org.eclipse.jface.viewers.Viewer;
47 import org.eclipse.jface.wizard.Wizard;
48 import org.eclipse.jface.wizard.WizardPage;
49 import org.eclipse.swt.SWT;
50 import org.eclipse.swt.layout.GridData;
51 import org.eclipse.swt.layout.GridLayout;
52 import org.eclipse.swt.widgets.Composite;
53 import org.eclipse.swt.widgets.Text;
54
55
56
57
58
59
60
61
62
63 public class EditTagWizard extends Wizard {
64 private final static Log log = LogFactory.getLog(EditTagWizard.class);
65
66
67 private ResourcesService resourcesService;
68 private SystemWorkbenchService systemWorkbenchService;
69
70 private String tagId;
71 private Node tagInstance;
72 private String tagPropName;
73
74
75 private Session session;
76 private Node tagParent;
77 private String taggableNodeType;
78 private String taggableParentPath;
79
80
81 private Text newTitleTxt;
82 private Text newDescTxt;
83
84
85
86
87
88
89
90
91
92 public EditTagWizard(ResourcesService resourcesService, SystemWorkbenchService systemWorkbenchService,
93 Node tagInstanceNode, String tagId, String tagPropName) {
94 this.resourcesService = resourcesService;
95 this.systemWorkbenchService = systemWorkbenchService;
96 this.tagId = tagId;
97 this.tagInstance = tagInstanceNode;
98 this.tagPropName = tagPropName;
99
100 session = ConnectJcrUtils.getSession(tagInstance);
101 tagParent = resourcesService.getTagLikeResourceParent(session, tagId);
102 taggableNodeType = ConnectJcrUtils.get(tagParent, ResourcesNames.RESOURCES_TAGGABLE_NODE_TYPE);
103 taggableParentPath = ConnectJcrUtils.get(tagParent, ResourcesNames.RESOURCES_TAGGABLE_PARENT_PATH);
104 }
105
106 @Override
107 public void addPages() {
108 try {
109
110 String title = "Rename [" + ConnectJcrUtils.get(tagInstance, Property.JCR_TITLE)
111 + "] and update existing related contacts";
112 setWindowTitle(title);
113 MainInfoPage inputPage = new MainInfoPage("Configure");
114 addPage(inputPage);
115 RecapPage recapPage = new RecapPage("Validate and launch");
116 addPage(recapPage);
117 } catch (Exception e) {
118 throw new ConnectException("Cannot add page to wizard", e);
119 }
120 }
121
122
123
124
125
126 @Override
127 public boolean performFinish() {
128 try {
129 String oldTitle = ConnectJcrUtils.get(tagInstance, Property.JCR_TITLE);
130 String newTitle = newTitleTxt.getText();
131 String newDesc = newDescTxt.getText();
132
133
134 String errMsg = null;
135 if (EclipseUiUtils.isEmpty(newTitle))
136 errMsg = "New value cannot be blank or an empty string";
137 else if (oldTitle.equals(newTitle))
138 errMsg = "New value is the same as old one.\n" + "Either enter a new one or press cancel.";
139 else if (resourcesService.getRegisteredTag(tagInstance.getSession(), tagId, newTitle) != null)
140 errMsg = "The new chosen value is already used.\n" + "Either enter a new one or press cancel.";
141
142 if (errMsg != null) {
143 MessageDialog.openError(getShell(), "Unvalid information", errMsg);
144 return false;
145 }
146
147 new UpdateTagAndInstancesJob(resourcesService, tagInstance, newTitle, newDesc).schedule();
148 return true;
149 } catch (RepositoryException re) {
150 throw new ConnectException("unable to update title for tag like resource " + tagInstance, re);
151 }
152 }
153
154 @Override
155 public boolean performCancel() {
156 return true;
157 }
158
159 @Override
160 public boolean canFinish() {
161 return getContainer().getCurrentPage().getNextPage() == null;
162 }
163
164 protected class MainInfoPage extends WizardPage {
165 private static final long serialVersionUID = 1L;
166
167 public MainInfoPage(String pageName) {
168 super(pageName);
169 setTitle("Enter a new title");
170 setMessage("As reminder, former value was: " + ConnectJcrUtils.get(tagInstance, Property.JCR_TITLE));
171 }
172
173 public void createControl(Composite parent) {
174 Composite body = new Composite(parent, SWT.NONE);
175 body.setLayout(new GridLayout(2, false));
176
177
178 ConnectUiUtils.createBoldLabel(body, "Title");
179 newTitleTxt = new Text(body, SWT.BORDER);
180 newTitleTxt.setMessage("was: " + ConnectJcrUtils.get(tagInstance, Property.JCR_TITLE));
181 newTitleTxt.setText(ConnectJcrUtils.get(tagInstance, Property.JCR_TITLE));
182 newTitleTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
183
184
185 ConnectUiUtils.createBoldLabel(body, "Description", SWT.TOP);
186 newDescTxt = new Text(body, SWT.BORDER | SWT.MULTI | SWT.WRAP);
187 newDescTxt.setMessage("was: " + ConnectJcrUtils.get(tagInstance, Property.JCR_DESCRIPTION));
188 newDescTxt.setText(ConnectJcrUtils.get(tagInstance, Property.JCR_DESCRIPTION));
189 newDescTxt.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
190
191 setControl(body);
192 newTitleTxt.setFocus();
193 }
194 }
195
196 protected class RecapPage extends WizardPage {
197 private static final long serialVersionUID = 1L;
198
199 public RecapPage(String pageName) {
200 super(pageName);
201 setTitle("Check and confirm");
202 setMessage("The below listed items will be impacted.\nAre you sure you want to procede ?");
203 }
204
205 public void createControl(Composite parent) {
206 Composite body = new Composite(parent, SWT.NONE);
207 body.setLayout(EclipseUiUtils.noSpaceGridLayout());
208 ArrayList<ConnectColumnDefinition> colDefs = new ArrayList<ConnectColumnDefinition>();
209 colDefs.add(new ConnectColumnDefinition(taggableNodeType, Property.JCR_TITLE, PropertyType.STRING,
210 "Display Name", new TitleIconRowLP(systemWorkbenchService, taggableNodeType, Property.JCR_TITLE),
211 300));
212
213 VirtualJcrTableViewer tableCmp = new VirtualJcrTableViewer(body, SWT.MULTI, colDefs);
214 TableViewer membersViewer = tableCmp.getTableViewer();
215 membersViewer.setContentProvider(new MyLazyContentProvider(membersViewer));
216 refreshFilteredList(membersViewer);
217 tableCmp.setLayoutData(EclipseUiUtils.fillAll());
218 setControl(body);
219 }
220 }
221
222
223 protected void refreshFilteredList(TableViewer membersViewer) {
224 String currVal = ConnectJcrUtils.get(tagInstance, Property.JCR_TITLE);
225 try {
226 QueryManager queryManager = session.getWorkspace().getQueryManager();
227 QueryObjectModelFactory factory = queryManager.getQOMFactory();
228 Selector source = factory.selector(taggableNodeType, taggableNodeType);
229
230 StaticOperand so = factory.literal(session.getValueFactory().createValue(currVal));
231 DynamicOperand dyo = factory.propertyValue(source.getSelectorName(), tagPropName);
232 Constraint constraint = factory.comparison(dyo, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, so);
233
234 Constraint subTree = factory.descendantNode(source.getSelectorName(), taggableParentPath);
235 constraint = ConnectJcrUtils.localAnd(factory, constraint, subTree);
236
237 Ordering order = factory.ascending(factory.propertyValue(source.getSelectorName(), Property.JCR_TITLE));
238 Ordering[] orderings = { order };
239 QueryObjectModel query = factory.createQuery(source, constraint, orderings, null);
240 QueryResult result = query.execute();
241 Row[] rows = ConnectJcrUtils.rowIteratorToArray(result.getRows());
242 setViewerInput(membersViewer, rows);
243
244 } catch (RepositoryException e) {
245 throw new ConnectException("Unable to list entities for tag like property instance " + currVal, e);
246 }
247 }
248
249
250 protected void setViewerInput(TableViewer membersViewer, Row[] rows) {
251 membersViewer.setInput(rows);
252
253 membersViewer.setItemCount(rows.length);
254 membersViewer.refresh();
255 }
256
257 private class MyLazyContentProvider implements ILazyContentProvider {
258 private static final long serialVersionUID = 1L;
259 private TableViewer viewer;
260 private Row[] elements;
261
262 public MyLazyContentProvider(TableViewer viewer) {
263 this.viewer = viewer;
264 }
265
266 public void dispose() {
267 }
268
269 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
270
271
272 viewer.setSelection(null);
273 this.elements = (Row[]) newInput;
274 }
275
276 public void updateElement(int index) {
277 viewer.replace(elements[index], index);
278 }
279 }
280
281
282 private class UpdateTagAndInstancesJob extends PrivilegedJob {
283
284 private Repository repository;
285 private ResourcesService resourcesService;
286 private String tagPath;
287 private String newTitle, newDesc;
288
289
290 private String tagJcrId;
291
292
293 public UpdateTagAndInstancesJob(ResourcesService resourceService, Node tagInstance, String newTitle,
294 String newDesc) {
295 super("Updating");
296 this.resourcesService = resourceService;
297 this.newTitle = newTitle;
298 this.newDesc = newDesc;
299 try {
300 repository = tagInstance.getSession().getRepository();
301 tagPath = tagInstance.getPath();
302 } catch (RepositoryException e) {
303 throw new ConnectException("Unable to init " + "tag instance batch update for " + tagId, e);
304 }
305
306 }
307
308 protected IStatus doRun(IProgressMonitor progressMonitor) {
309 Session session = null;
310 try {
311 JcrMonitor monitor = new EclipseJcrMonitor(progressMonitor);
312 if (monitor != null && !monitor.isCanceled()) {
313 monitor.beginTask("Updating objects", -1);
314
315 session = repository.login();
316 Node tagInstance = session.getNode(tagPath);
317
318
319
320 ConnectJcrUtils.checkCOStatusBeforeUpdate(tagInstance);
321
322 resourcesService.updateTag(tagInstance, newTitle);
323
324 if (EclipseUiUtils.notEmpty(newDesc))
325 tagInstance.setProperty(Property.JCR_DESCRIPTION, newDesc);
326 else if (tagInstance.hasProperty(Property.JCR_DESCRIPTION))
327 tagInstance.getProperty(Property.JCR_DESCRIPTION).remove();
328
329
330 if (tagInstance.isNodeType(NodeType.MIX_VERSIONABLE))
331 ConnectJcrUtils.saveAndPublish(tagInstance, true);
332 else
333 tagInstance.getSession().save();
334 monitor.worked(1);
335 tagJcrId = tagInstance.getIdentifier();
336 doRefresh();
337 }
338 } catch (Exception e) {
339 e.printStackTrace();
340 return new Status(IStatus.ERROR, "",
341 "Cannot edit tag and corresponding instances", e);
342 } finally {
343 JcrUtils.logoutQuietly(session);
344 }
345 return Status.OK_STATUS;
346 }
347
348 private void doRefresh() {
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368 }
369 }
370 }