]> git.argeo.org Git - gpl/argeo-slc.git/blob - legacy/org.argeo.slc.client.ui.dist/src/org/argeo/slc/client/ui/dist/wizards/FetchWizard.java
Merge remote-tracking branch 'origin/master' into testing
[gpl/argeo-slc.git] / legacy / org.argeo.slc.client.ui.dist / src / org / argeo / slc / client / ui / dist / wizards / FetchWizard.java
1 package org.argeo.slc.client.ui.dist.wizards;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import javax.jcr.Credentials;
9 import javax.jcr.Node;
10 import javax.jcr.NodeIterator;
11 import javax.jcr.Repository;
12 import javax.jcr.RepositoryException;
13 import javax.jcr.RepositoryFactory;
14 import javax.jcr.Session;
15
16 import org.argeo.api.NodeUtils;
17 import org.argeo.api.security.Keyring;
18 import org.argeo.cms.ArgeoNames;
19 import org.argeo.cms.ArgeoTypes;
20 import org.argeo.cms.ui.workbench.util.PrivilegedJob;
21 import org.argeo.eclipse.ui.EclipseJcrMonitor;
22 import org.argeo.jcr.JcrMonitor;
23 import org.argeo.jcr.JcrUtils;
24 import org.argeo.slc.SlcException;
25 import org.argeo.slc.client.ui.dist.DistPlugin;
26 import org.argeo.slc.client.ui.dist.utils.ViewerUtils;
27 import org.argeo.slc.repo.RepoConstants;
28 import org.argeo.slc.repo.RepoSync;
29 import org.argeo.slc.repo.RepoUtils;
30 import org.eclipse.core.runtime.IProgressMonitor;
31 import org.eclipse.core.runtime.IStatus;
32 import org.eclipse.core.runtime.Status;
33 import org.eclipse.jface.dialogs.MessageDialog;
34 import org.eclipse.jface.viewers.CheckStateChangedEvent;
35 import org.eclipse.jface.viewers.CheckboxTableViewer;
36 import org.eclipse.jface.viewers.ColumnLabelProvider;
37 import org.eclipse.jface.viewers.ICheckStateListener;
38 import org.eclipse.jface.viewers.IStructuredContentProvider;
39 import org.eclipse.jface.viewers.TableViewer;
40 import org.eclipse.jface.viewers.TableViewerColumn;
41 import org.eclipse.jface.viewers.Viewer;
42 import org.eclipse.jface.viewers.ViewerComparator;
43 import org.eclipse.jface.wizard.IWizardPage;
44 import org.eclipse.jface.wizard.Wizard;
45 import org.eclipse.jface.wizard.WizardPage;
46 import org.eclipse.swt.SWT;
47 import org.eclipse.swt.events.ModifyEvent;
48 import org.eclipse.swt.events.ModifyListener;
49 import org.eclipse.swt.events.SelectionAdapter;
50 import org.eclipse.swt.events.SelectionEvent;
51 import org.eclipse.swt.layout.GridData;
52 import org.eclipse.swt.layout.GridLayout;
53 import org.eclipse.swt.widgets.Button;
54 import org.eclipse.swt.widgets.Combo;
55 import org.eclipse.swt.widgets.Composite;
56 import org.eclipse.swt.widgets.Label;
57 import org.eclipse.swt.widgets.Table;
58 import org.eclipse.swt.widgets.Text;
59
60 /**
61 * Defines parameters for the fetch process and run it using a {@link RepoSync}
62 * object.
63 */
64 public class FetchWizard extends Wizard {
65 // private final static Log log = LogFactory.getLog(FetchWizard.class);
66
67 // Business objects
68 private Keyring keyring;
69 private RepositoryFactory repositoryFactory;
70 private Session currSession;
71 private Node targetRepoNode, sourceRepoNode;
72
73 private List<WkspObject> selectedWorkspaces = new ArrayList<WkspObject>();
74
75 // The pages
76 private ChooseWkspPage chooseWkspPage;
77 private RecapPage recapPage;
78
79 // Cache the advanced pages
80 private Map<WkspObject, AdvancedFetchPage> advancedPages = new HashMap<FetchWizard.WkspObject, FetchWizard.AdvancedFetchPage>();
81
82 // Controls with parameters
83 private Button filesOnlyBtn;
84 private Button advancedBtn;
85 private CheckboxTableViewer wkspViewer;
86
87 public FetchWizard(Keyring keyring, RepositoryFactory repositoryFactory,
88 Repository nodeRepository) {
89 super();
90 this.keyring = keyring;
91 this.repositoryFactory = repositoryFactory;
92 try {
93 currSession = nodeRepository.login();
94 } catch (RepositoryException e) {
95 throw new SlcException(
96 "Unexpected error while initializing fetch wizard", e);
97 }
98 }
99
100 @Override
101 public void dispose() {
102 JcrUtils.logoutQuietly(currSession);
103 super.dispose();
104 }
105
106 @Override
107 public void addPages() {
108 try {
109 chooseWkspPage = new ChooseWkspPage();
110 addPage(chooseWkspPage);
111 recapPage = new RecapPage();
112 addPage(recapPage);
113 setWindowTitle("Define Fetch Procedure");
114 } catch (Exception e) {
115 throw new SlcException("Cannot add page to wizard ", e);
116 }
117 }
118
119 @Override
120 public boolean performFinish() {
121 if (!canFinish())
122 return false;
123 try {
124 // Target Repository
125 String targetRepoUri = targetRepoNode.getProperty(
126 ArgeoNames.ARGEO_URI).getString();
127 Repository targetRepo = RepoUtils.getRepository(repositoryFactory,
128 keyring, targetRepoNode);
129 Credentials targetCredentials = RepoUtils.getRepositoryCredentials(
130 keyring, targetRepoNode);
131
132 // Source Repository
133 String sourceRepoUri = sourceRepoNode.getProperty(
134 ArgeoNames.ARGEO_URI).getString();
135 Repository sourceRepo = RepoUtils.getRepository(repositoryFactory,
136 keyring, sourceRepoNode);
137 Credentials sourceCredentials = RepoUtils.getRepositoryCredentials(
138 keyring, sourceRepoNode);
139
140 String msg = "Your are about to fetch data from repository: \n\t"
141 + sourceRepoUri + "\ninto target repository: \n\t"
142 + targetRepoUri + "\nDo you really want to proceed ?";
143
144 boolean result = MessageDialog.openConfirm(DistPlugin.getDefault()
145 .getWorkbench().getDisplay().getActiveShell(),
146 "Confirm Fetch Launch", msg);
147
148 if (result) {
149 RepoSync repoSync = new RepoSync(sourceRepo, sourceCredentials,
150 targetRepo, targetCredentials);
151 repoSync.setTargetRepoUri(targetRepoUri);
152 repoSync.setSourceRepoUri(sourceRepoUri);
153
154 // Specify workspaces to synchronise
155 Map<String, String> wksps = new HashMap<String, String>();
156 for (Object obj : wkspViewer.getCheckedElements()) {
157 WkspObject stn = (WkspObject) obj;
158 wksps.put(stn.srcName, stn.targetName);
159 }
160 repoSync.setWkspMap(wksps);
161
162 // Set the import files only option
163 repoSync.setFilesOnly(filesOnlyBtn.getSelection());
164 FetchJob job = new FetchJob(repoSync);
165 job.setUser(true);
166 job.schedule();
167 }
168 } catch (Exception e) {
169 throw new SlcException(
170 "Unexpected error while launching the fetch", e);
171 }
172 return true;
173 }
174
175 // ///////////////////////////////
176 // ////// THE PAGES
177
178 private class ChooseWkspPage extends WizardPage {
179 private static final long serialVersionUID = 211336700788047638L;
180
181 private Map<String, Node> sourceReposMap;
182 private Combo chooseSourceRepoCmb;
183
184 public ChooseWkspPage() {
185 super("Main");
186 setTitle("Choose workspaces to fetch");
187 setDescription("Check 'advanced fetch' box to "
188 + "rename workspaces and fine tune the process");
189
190 // Initialise with registered Repositories
191 sourceReposMap = getSourceRepoUris();
192 }
193
194 public void createControl(Composite parent) {
195 Composite composite = new Composite(parent, SWT.NO_FOCUS);
196 composite.setLayout(new GridLayout(2, false));
197
198 // Choose source repository combo
199 new Label(composite, SWT.NONE)
200 .setText("Choose a source repository");
201 chooseSourceRepoCmb = new Combo(composite, SWT.BORDER
202 | SWT.V_SCROLL);
203 chooseSourceRepoCmb.setItems(sourceReposMap.keySet().toArray(
204 new String[sourceReposMap.size()]));
205 GridData gd = new GridData(GridData.FILL_HORIZONTAL);
206 chooseSourceRepoCmb.setLayoutData(gd);
207
208 // Check boxes
209 final Button selectAllBtn = new Button(composite, SWT.CHECK);
210 selectAllBtn.setText("Select/Unselect all");
211
212 advancedBtn = new Button(composite, SWT.CHECK);
213 advancedBtn.setText("Advanced fetch");
214 advancedBtn.setToolTipText("Check this for further "
215 + "parameterization of the fetch process");
216
217 // Workspace table
218 Table table = new Table(composite, SWT.H_SCROLL | SWT.V_SCROLL
219 | SWT.BORDER | SWT.CHECK);
220 gd = new GridData(SWT.FILL, SWT.FILL, true, true);
221 gd.horizontalSpan = 2;
222 table.setLayoutData(gd);
223 configureWkspTable(table);
224
225 // Import only files
226 filesOnlyBtn = new Button(composite, SWT.CHECK | SWT.WRAP);
227 filesOnlyBtn
228 .setText("Import only files (faster, a normalized action should be launched once done)");
229 filesOnlyBtn.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false,
230 false, 2, 1));
231
232 // Listeners
233 selectAllBtn.addSelectionListener(new SelectionAdapter() {
234 private static final long serialVersionUID = -2071840477444152170L;
235
236 public void widgetSelected(SelectionEvent e) {
237 wkspViewer.setAllChecked(selectAllBtn.getSelection());
238 getContainer().updateButtons();
239 }
240 });
241
242 // advancedBtn.addSelectionListener(new SelectionAdapter() {
243 // public void widgetSelected(SelectionEvent e) {
244 // if (advancedBtn.getSelection()){
245 //
246 // }
247 // wkspViewer.setAllChecked();
248 // }
249 // });
250
251 chooseSourceRepoCmb.addModifyListener(new ModifyListener() {
252 private static final long serialVersionUID = 932462568382594523L;
253
254 public void modifyText(ModifyEvent e) {
255 String chosenUri = chooseSourceRepoCmb
256 .getItem(chooseSourceRepoCmb.getSelectionIndex());
257 sourceRepoNode = sourceReposMap.get(chosenUri);
258 wkspViewer.setInput(sourceRepoNode);
259 }
260 });
261
262 wkspViewer.addCheckStateListener(new ICheckStateListener() {
263 public void checkStateChanged(CheckStateChangedEvent event) {
264 getContainer().updateButtons();
265 }
266 });
267
268 // Initialise to first available repo
269 if (chooseSourceRepoCmb.getItemCount() > 0)
270 chooseSourceRepoCmb.select(0);
271
272 // Compulsory
273 setControl(composite);
274 }
275
276 @Override
277 public boolean isPageComplete() {
278 return wkspViewer.getCheckedElements().length != 0;
279 }
280
281 @Override
282 public IWizardPage getNextPage() {
283 // WARNING: page are added and never removed.
284 if (advancedBtn.getSelection()
285 && wkspViewer.getCheckedElements().length != 0) {
286 IWizardPage toReturn = null;
287 for (Object obj : wkspViewer.getCheckedElements()) {
288 WkspObject curr = (WkspObject) obj;
289 // currSelecteds.add(curr);
290 AdvancedFetchPage page;
291 if (!advancedPages.containsKey(curr)) {
292 page = new AdvancedFetchPage(curr.srcName, curr);
293 addPage(page);
294 advancedPages.put(curr, page);
295 } else
296 page = advancedPages.get(curr);
297 if (toReturn == null)
298 toReturn = page;
299 }
300 return toReturn;
301 } else {
302 return recapPage;
303 }
304 }
305
306 // Configure the workspace table
307 private void configureWkspTable(Table table) {
308 table.setLinesVisible(true);
309 table.setHeaderVisible(true);
310 wkspViewer = new CheckboxTableViewer(table);
311
312 // WORKSPACE COLUMNS
313 TableViewerColumn column = ViewerUtils.createTableViewerColumn(
314 wkspViewer, "Source names", SWT.NONE, 250);
315 column.setLabelProvider(new ColumnLabelProvider() {
316 private static final long serialVersionUID = 5906079281065061967L;
317
318 @Override
319 public String getText(Object element) {
320 return ((WkspObject) element).srcName;
321 }
322 });
323
324 // column = ViewerUtils.createTableViewerColumn(wkspViewer, "Size",
325 // SWT.NONE, 250);
326 // column.setLabelProvider(new ColumnLabelProvider() {
327 // @Override
328 // public String getText(Object element) {
329 // return ((WkspObject) element).getFormattedSize();
330 // }
331 // });
332
333 wkspViewer.setContentProvider(new WkspContentProvider());
334 // A basic comparator
335 wkspViewer.setComparator(new ViewerComparator());
336 }
337 }
338
339 private class AdvancedFetchPage extends WizardPage {
340 private static final long serialVersionUID = 1109183561920445169L;
341
342 private final WkspObject currentWorkspace;
343
344 private Text targetNameTxt;
345
346 protected AdvancedFetchPage(String pageName, WkspObject currentWorkspace) {
347 super(pageName);
348 this.currentWorkspace = currentWorkspace;
349 }
350
351 @Override
352 public void setVisible(boolean visible) {
353 super.setVisible(visible);
354 if (visible) {
355 String msg = "Define advanced parameters to fetch workspace "
356 + currentWorkspace.srcName;
357 setMessage(msg);
358 targetNameTxt.setText(currentWorkspace.targetName);
359 }
360 // else
361 // currentWorkspace.targetName = targetNameTxt.getText();
362 }
363
364 public void createControl(Composite parent) {
365 Composite body = new Composite(parent, SWT.NO_FOCUS);
366 body.setLayout(new GridLayout(2, false));
367 new Label(body, SWT.NONE).setText("Choose a new name");
368 targetNameTxt = new Text(body, SWT.BORDER);
369 targetNameTxt.setLayoutData(new GridData(SWT.FILL, SWT.CENTER,
370 true, false));
371 setControl(body);
372 }
373
374 protected WkspObject getWorkspaceObject() {
375 currentWorkspace.targetName = targetNameTxt.getText();
376 return currentWorkspace;
377 }
378
379 @Override
380 public IWizardPage getNextPage() {
381 // WARNING: page are added and never removed.
382 // IWizardPage toReturn = null;
383 // IWizardPage[] pages = ((Wizard) getContainer()).getPages();
384 Object[] selected = wkspViewer.getCheckedElements();
385 for (int i = 0; i < selected.length - 1; i++) {
386 WkspObject curr = (WkspObject) selected[i];
387 if (curr.equals(currentWorkspace))
388 return advancedPages.get((WkspObject) selected[i + 1]);
389 }
390 return recapPage;
391 }
392 }
393
394 private class RecapPage extends WizardPage {
395 private static final long serialVersionUID = -7064862323304300989L;
396 private TableViewer recapViewer;
397
398 public RecapPage() {
399 super("Validate and launch");
400 setTitle("Validate and launch");
401 }
402
403 @Override
404 public boolean isPageComplete() {
405 return isCurrentPage();
406 }
407
408 public IWizardPage getNextPage() {
409 // always last....
410 return null;
411 }
412
413 @Override
414 public void setVisible(boolean visible) {
415 super.setVisible(visible);
416 if (visible) {
417 try {
418 String targetRepoUri = targetRepoNode.getProperty(
419 ArgeoNames.ARGEO_URI).getString();
420 String sourceRepoUri = sourceRepoNode.getProperty(
421 ArgeoNames.ARGEO_URI).getString();
422
423 String msg = "Fetch data from: " + sourceRepoUri
424 + "\ninto target repository: " + targetRepoUri;
425 // + "\nDo you really want to proceed ?";
426 setMessage(msg);
427
428 // update values that will be used for the fetch
429 selectedWorkspaces.clear();
430
431 for (Object obj : wkspViewer.getCheckedElements()) {
432 WkspObject curr = (WkspObject) obj;
433
434 if (advancedBtn.getSelection()) {
435 AdvancedFetchPage page = advancedPages.get(curr);
436 selectedWorkspaces.add(page.getWorkspaceObject());
437 } else
438 selectedWorkspaces.add(curr);
439 }
440 recapViewer.setInput(selectedWorkspaces);
441 recapViewer.refresh();
442
443 } catch (RepositoryException re) {
444 throw new SlcException("Unable to get repositories URIs",
445 re);
446 }
447 }
448 }
449
450 public void createControl(Composite parent) {
451 Table table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL
452 | SWT.BORDER);
453 table.setLinesVisible(true);
454 table.setHeaderVisible(true);
455 recapViewer = new TableViewer(table);
456
457 // WORKSPACE COLUMNS
458 TableViewerColumn column = ViewerUtils.createTableViewerColumn(
459 recapViewer, "Sources", SWT.NONE, 250);
460 column.setLabelProvider(new ColumnLabelProvider() {
461 private static final long serialVersionUID = 3913459002502680377L;
462
463 @Override
464 public String getText(Object element) {
465 return ((WkspObject) element).srcName;
466 }
467 });
468
469 column = ViewerUtils.createTableViewerColumn(recapViewer,
470 "targets", SWT.NONE, 250);
471 column.setLabelProvider(new ColumnLabelProvider() {
472 private static final long serialVersionUID = -517920072332563632L;
473
474 @Override
475 public String getText(Object element) {
476 return ((WkspObject) element).targetName;
477 }
478 });
479
480 recapViewer.setContentProvider(new IStructuredContentProvider() {
481 private static final long serialVersionUID = 4926999891003040865L;
482
483 public void inputChanged(Viewer viewer, Object oldInput,
484 Object newInput) {
485 // TODO Auto-generated method stub
486 }
487
488 public void dispose() {
489 }
490
491 public Object[] getElements(Object inputElement) {
492 return selectedWorkspaces.toArray();
493 }
494 });
495
496 // A basic comparator
497 recapViewer.setComparator(new ViewerComparator());
498 setControl(table);
499 }
500 }
501
502 /**
503 * Define the privileged job that will be run asynchronously to accomplish
504 * the sync
505 */
506 private class FetchJob extends PrivilegedJob {
507 private RepoSync repoSync;
508
509 public FetchJob(RepoSync repoSync) {
510 super("Fetch");
511 this.repoSync = repoSync;
512 }
513
514 @Override
515 protected IStatus doRun(IProgressMonitor progressMonitor) {
516 try {
517 JcrMonitor monitor = new EclipseJcrMonitor(progressMonitor);
518 repoSync.setMonitor(monitor);
519 repoSync.run();
520 } catch (Exception e) {
521 return new Status(IStatus.ERROR, DistPlugin.PLUGIN_ID,
522 "Cannot fetch repository", e);
523 }
524 return Status.OK_STATUS;
525 }
526 }
527
528 // ///////////////////////
529 // Local classes
530 private class WkspObject {
531 protected final String srcName;
532 protected String targetName;
533
534 protected WkspObject(String srcName) {
535 this.srcName = srcName;
536 this.targetName = srcName;
537 }
538
539 @Override
540 public String toString() {
541 return "[" + srcName + " to " + targetName + "]";
542 }
543 }
544
545 // private class WkspComparator extends ViewerComparator {
546 //
547 // }
548
549 private class WkspContentProvider implements IStructuredContentProvider {
550 private static final long serialVersionUID = -925058051598536307L;
551 // caches current repo
552 private Node currSourceNodeRepo;
553 private Repository currSourceRepo;
554 private Credentials currSourceCred;
555
556 private List<WkspObject> workspaces = new ArrayList<WkspObject>();
557
558 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
559 if (newInput != null && newInput instanceof Node) {
560 Session session = null;
561 try {
562 Node newRepoNode = (Node) newInput;
563 if (currSourceNodeRepo == null
564 || !newRepoNode.getPath().equals(
565 currSourceNodeRepo.getPath())) {
566
567 // update cache
568 currSourceNodeRepo = newRepoNode;
569 currSourceRepo = RepoUtils.getRepository(
570 repositoryFactory, keyring, currSourceNodeRepo);
571 currSourceCred = RepoUtils.getRepositoryCredentials(
572 keyring, currSourceNodeRepo);
573
574 // reset workspace list
575 wkspViewer.setAllChecked(false);
576 workspaces.clear();
577 // FIXME make it more generic
578 session = currSourceRepo.login(currSourceCred,RepoConstants.DEFAULT_DEFAULT_WORKSPACE);
579 // remove unvalid elements
580 for (String name : session.getWorkspace()
581 .getAccessibleWorkspaceNames())
582 // TODO implement a cleaner way to filter
583 // workspaces out
584 if (name.lastIndexOf('-') > 0) {
585 WkspObject currWksp = new WkspObject(name);
586 // compute wkspace size
587 // TODO implement this
588 // Session currSession = null;
589 // try {
590 // currSession = currSourceRepo.login(
591 // currSourceCred, name);
592 // currWksp.size = JcrUtils
593 // .getNodeApproxSize(currSession
594 // .getNode("/"));
595 //
596 // } catch (RepositoryException re) {
597 // log.warn(
598 // "unable to compute size of workspace "
599 // + name, re);
600 // } finally {
601 // JcrUtils.logoutQuietly(currSession);
602 // }
603 workspaces.add(currWksp);
604 }
605 }
606
607 } catch (RepositoryException e) {
608 throw new SlcException("Unexpected error while "
609 + "initializing fetch wizard", e);
610 } finally {
611 JcrUtils.logoutQuietly(session);
612 }
613 viewer.refresh();
614 }
615 }
616
617 public void dispose() {
618 }
619
620 public Object[] getElements(Object obj) {
621 return workspaces.toArray();
622 }
623 }
624
625 // ////////////////////////////
626 // // Helpers
627
628 // populate available source repo list
629 private Map<String, Node> getSourceRepoUris() {
630 try {
631 Node repoList = currSession.getNode(NodeUtils.getUserHome(
632 currSession).getPath()
633 + RepoConstants.REPOSITORIES_BASE_PATH);
634
635 String targetRepoUri = null;
636 if (targetRepoNode != null) {
637 targetRepoUri = targetRepoNode
638 .getProperty(ArgeoNames.ARGEO_URI).getString();
639 }
640 NodeIterator ni = repoList.getNodes();
641 // List<String> sourceRepoNames = new ArrayList<String>();
642 // // caches a map of the source repo nodes with their URI as a key
643 // // to ease further processing
644 Map<String, Node> sourceReposMap = new HashMap<String, Node>();
645 while (ni.hasNext()) {
646 Node currNode = ni.nextNode();
647 if (currNode.isNodeType(ArgeoTypes.ARGEO_REMOTE_REPOSITORY)) {
648 String currUri = currNode.getProperty(ArgeoNames.ARGEO_URI)
649 .getString();
650 if (targetRepoUri == null || !targetRepoUri.equals(currUri)) {
651 sourceReposMap.put(currUri, currNode);
652 // sourceRepoNames.add(currUri);
653 }
654 }
655 }
656 return sourceReposMap;
657 // sourceRepoNames.toArray(new String[sourceRepoNames
658 // .size()]);
659 } catch (RepositoryException e) {
660 throw new SlcException("Error while getting repo aliases", e);
661 }
662 }
663
664 public void setTargetRepoNode(Node targetRepoNode) {
665 this.targetRepoNode = targetRepoNode;
666 }
667
668 public void setSourceRepoNode(Node sourceRepoNode) {
669 this.sourceRepoNode = sourceRepoNode;
670 }
671 }