1 package org
.argeo
.suite
.workbench
.commands
;
3 import static org
.argeo
.connect
.util
.JxlUtils
.getStringValue
;
4 import static org
.argeo
.eclipse
.ui
.EclipseUiUtils
.notEmpty
;
7 import java
.io
.FileInputStream
;
8 import java
.io
.FileOutputStream
;
9 import java
.io
.IOException
;
10 import java
.io
.InputStream
;
11 import java
.io
.OutputStream
;
12 import java
.util
.Collections
;
13 import java
.util
.HashMap
;
15 import java
.util
.UUID
;
17 import javax
.jcr
.Node
;
18 import javax
.jcr
.Property
;
19 import javax
.jcr
.Repository
;
20 import javax
.jcr
.RepositoryException
;
21 import javax
.jcr
.Session
;
23 import org
.apache
.commons
.io
.IOUtils
;
24 import org
.argeo
.connect
.ConnectConstants
;
25 import org
.argeo
.connect
.ConnectNames
;
26 import org
.argeo
.connect
.resources
.ResourcesNames
;
27 import org
.argeo
.connect
.resources
.ResourcesService
;
28 import org
.argeo
.connect
.util
.ConnectJcrUtils
;
29 import org
.argeo
.connect
.util
.JxlUtils
;
30 import org
.argeo
.eclipse
.ui
.EclipseUiUtils
;
31 import org
.argeo
.jcr
.JcrUtils
;
32 import org
.argeo
.people
.ContactValueCatalogs
;
33 import org
.argeo
.people
.PeopleException
;
34 import org
.argeo
.people
.PeopleNames
;
35 import org
.argeo
.people
.PeopleService
;
36 import org
.argeo
.people
.PeopleTypes
;
37 import org
.argeo
.people
.util
.PeopleJcrUtils
;
38 import org
.argeo
.people
.util
.PersonJcrUtils
;
39 import org
.argeo
.suite
.SuiteException
;
40 import org
.argeo
.suite
.workbench
.AsUiPlugin
;
41 import org
.eclipse
.core
.commands
.AbstractHandler
;
42 import org
.eclipse
.core
.commands
.ExecutionEvent
;
43 import org
.eclipse
.core
.commands
.ExecutionException
;
44 import org
.eclipse
.jface
.wizard
.Wizard
;
45 import org
.eclipse
.jface
.wizard
.WizardDialog
;
46 import org
.eclipse
.jface
.wizard
.WizardPage
;
47 import org
.eclipse
.rap
.fileupload
.FileDetails
;
48 import org
.eclipse
.rap
.fileupload
.FileUploadEvent
;
49 import org
.eclipse
.rap
.fileupload
.FileUploadHandler
;
50 import org
.eclipse
.rap
.fileupload
.FileUploadListener
;
51 import org
.eclipse
.rap
.fileupload
.FileUploadReceiver
;
52 import org
.eclipse
.rap
.rwt
.service
.ServerPushSession
;
53 import org
.eclipse
.rap
.rwt
.widgets
.FileUpload
;
54 import org
.eclipse
.swt
.SWT
;
55 import org
.eclipse
.swt
.events
.ModifyEvent
;
56 import org
.eclipse
.swt
.events
.ModifyListener
;
57 import org
.eclipse
.swt
.events
.SelectionAdapter
;
58 import org
.eclipse
.swt
.events
.SelectionEvent
;
59 import org
.eclipse
.swt
.layout
.GridData
;
60 import org
.eclipse
.swt
.layout
.GridLayout
;
61 import org
.eclipse
.swt
.widgets
.Combo
;
62 import org
.eclipse
.swt
.widgets
.Composite
;
63 import org
.eclipse
.swt
.widgets
.Control
;
64 import org
.eclipse
.swt
.widgets
.Label
;
65 import org
.eclipse
.swt
.widgets
.Shell
;
66 import org
.eclipse
.ui
.handlers
.HandlerUtil
;
71 /** Open a one page wizard to import an EXCEL 2003 legacy organisation file */
72 public class ImportEntities
extends AbstractHandler
implements PeopleNames
{
74 public final static String ID
= AsUiPlugin
.PLUGIN_ID
+ ".importEntities";
76 // public final static String PARAM_NODE_TYPE = "param.nodeType";
78 private static final Map
<String
, String
> KNOWN_TEMPLATES
;
80 Map
<String
, String
> tmpMap
= new HashMap
<String
, String
>();
81 tmpMap
.put("Organisations", PeopleTypes
.PEOPLE_ORG
);
82 KNOWN_TEMPLATES
= Collections
.unmodifiableMap(tmpMap
);
85 // TODO make this configurable
86 private final static String IMPORT_ENCODING
= "ISO-8859-1";// "UTF-8";
88 /* DEPENDENCY INJECTION */
89 private Repository repository
;
90 private ResourcesService resourcesService
;
91 private PeopleService peopleService
;
93 public Object
execute(final ExecutionEvent event
) throws ExecutionException
{
94 // String jcrId = event.getParameter(PARAM_NODE_TYPE);
96 Wizard wizard
= new ImportMappingFileWizard(HandlerUtil
.getActiveShell(event
),
97 "Upload legacy contact via Excel file import");
98 WizardDialog dialog
= new WizardDialog(HandlerUtil
.getActiveShell(event
), wizard
);
103 /** One page wizard to import a EXCEL 2003 Mapping files */
104 private class ImportMappingFileWizard
extends Wizard
{
106 // Various UI Objects
107 private UserInputPage userInputPage
;
108 private Combo resourceTypeCombo
;
111 private FileUpload fileUpload
;
112 private Label fileNameLabel
;
113 private ServerPushSession pushSession
;
116 public ImportMappingFileWizard(Shell parentShell
, String title
) {
117 setWindowTitle(title
);
121 public void addPages() {
123 userInputPage
= new UserInputPage("User input page");
124 addPage(userInputPage
);
125 } catch (Exception e
) {
126 throw new SuiteException("Cannot add page to wizard", e
);
130 /** Performs the real import. */
132 public boolean performFinish() {
133 // Session session = null;
134 // String templateName =
135 // resourceTypeCombo.getItem(resourceTypeCombo.getSelectionIndex());
136 // String type = KNOWN_TEMPLATES.get(templateName);
137 importDefaultOrgFile(file
);
142 public boolean performCancel() {
147 public boolean canFinish() {
148 if (resourceTypeCombo
.getSelectionIndex() < 0) {
149 userInputPage
.setErrorMessage("Please choose an entity type");
151 } else if (file
== null) {
152 userInputPage
.setErrorMessage("Please upload a file");
155 userInputPage
.setErrorMessage(null);
160 private class UserInputPage
extends WizardPage
{
161 private static final long serialVersionUID
= 1L;
163 public UserInputPage(String pageName
) {
165 setTitle("Upload an Excel 2003 file (.xls)");
168 public void createControl(Composite parent
) {
169 parent
.setLayout(new GridLayout(1, false));
170 Composite composite
= new Composite(parent
, SWT
.NONE
);
171 composite
.setLayout(new GridLayout(2, false));
172 composite
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
175 resourceTypeCombo
= createLC(composite
, "Type");
176 resourceTypeCombo
.addModifyListener(new ModifyListener() {
177 private static final long serialVersionUID
= 1L;
180 public void modifyText(ModifyEvent event
) {
181 getWizard().getContainer().updateButtons();
184 resourceTypeCombo
.setItems(KNOWN_TEMPLATES
.keySet().toArray(new String
[0]));
185 resourceTypeCombo
.select(0);
188 Label lbl
= new Label(composite
, SWT
.NONE
);
189 lbl
.setText("Chosen file");
190 lbl
.setFont(EclipseUiUtils
.getBoldFont(composite
));
191 Composite uploadCmp
= new Composite(composite
, SWT
.NONE
);
192 uploadCmp
.setLayoutData(EclipseUiUtils
.fillWidth());
193 createFileUploadArea(uploadCmp
);
194 setControl(composite
);
198 private Control
createFileUploadArea(Composite parent
) {
199 GridLayout gl
= EclipseUiUtils
.noSpaceGridLayout(new GridLayout(2, false));
200 gl
.horizontalSpacing
= 5;
201 parent
.setLayout(gl
);
203 fileNameLabel
= new Label(parent
, SWT
.NONE
| SWT
.BEGINNING
);
204 fileNameLabel
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false));
206 fileUpload
= new FileUpload(parent
, SWT
.NONE
);
207 fileUpload
.setText("Browse...");
208 fileUpload
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, false, false));
210 final String url
= startUploadReceiver();
211 pushSession
= new ServerPushSession();
213 fileUpload
.addSelectionListener(new SelectionAdapter() {
214 private static final long serialVersionUID
= 1L;
217 public void widgetSelected(SelectionEvent e
) {
218 String fileName
= fileUpload
.getFileName();
219 fileNameLabel
.setText(fileName
== null ?
"" : fileName
);
221 fileUpload
.submit(url
);
227 private String
startUploadReceiver() {
228 MyFileUploadReceiver receiver
= new MyFileUploadReceiver();
229 FileUploadHandler uploadHandler
= new FileUploadHandler(receiver
);
230 uploadHandler
.addUploadListener(new FileUploadListener() {
232 public void uploadProgress(FileUploadEvent event
) {
233 // handle upload progress
236 public void uploadFailed(FileUploadEvent event
) {
237 ImportMappingFileWizard
.this.userInputPage
238 .setErrorMessage("upload failed: " + event
.getException());
241 public void uploadFinished(FileUploadEvent event
) {
242 fileNameLabel
.getDisplay().asyncExec(new Runnable() {
244 ImportMappingFileWizard
.this.getContainer().updateButtons();
250 return uploadHandler
.getUploadUrl();
253 private class MyFileUploadReceiver
extends FileUploadReceiver
{
255 private static final String TEMP_FILE_PREFIX
= "fileupload_";
258 public void receive(InputStream dataStream
, FileDetails details
) throws IOException
{
259 File result
= File
.createTempFile(TEMP_FILE_PREFIX
, "");
260 FileOutputStream outputStream
= new FileOutputStream(result
);
262 copy(dataStream
, outputStream
);
265 outputStream
.close();
273 private void copy(InputStream inputStream
, OutputStream outputStream
) throws IOException
{
274 byte[] buffer
= new byte[8192];
275 boolean finished
= false;
277 int bytesRead
= inputStream
.read(buffer
);
278 if (bytesRead
!= -1) {
279 outputStream
.write(buffer
, 0, bytesRead
);
286 /** Creates label and Combo. */
287 protected Combo
createLC(Composite parent
, String label
) {
288 Label lbl
= new Label(parent
, SWT
.RIGHT
);
290 lbl
.setFont(EclipseUiUtils
.getBoldFont(parent
));
291 lbl
.setLayoutData(new GridData(SWT
.RIGHT
, SWT
.CENTER
, false, false));
292 Combo combo
= new Combo(parent
, SWT
.READ_ONLY
);
293 combo
.setLayoutData(new GridData(SWT
.FILL
, SWT
.CENTER
, true, false));
298 // Legacy Organisations
299 private Node
importDefaultOrgFile(File file
) {
300 InputStream in
= null;
302 in
= new FileInputStream(file
);
303 return importDefaultOrgFile(in
);
304 } catch (IOException e
) {
305 throw new SuiteException("Cannot import mapping file", e
);
307 IOUtils
.closeQuietly(in
);
311 private Node
createDraftNode(Node parent
, String mainMixin
) throws RepositoryException
{
312 String uuid
= UUID
.randomUUID().toString();
313 Node tmpNode
= parent
.addNode(uuid
);
314 tmpNode
.addMixin(mainMixin
);
315 tmpNode
.setProperty(ConnectNames
.CONNECT_UID
, uuid
);
319 private void importOrgEmployees(Node tmpParent
, Node targetParent
, Node newOrgNode
, String coworkersStr
)
320 throws RepositoryException
{
321 String
[] coworkers
= coworkersStr
.split("\\n");
322 loop
: for (String line
: coworkers
) {
323 if (EclipseUiUtils
.isEmpty(line
))
326 int index
= line
.indexOf(' ');
327 String firstName
= null;
328 String lastName
= null;
329 String position
= null;
333 firstName
= line
.substring(0, index
);
334 line
= line
.substring(index
);
336 index
= line
.indexOf('(');
340 lastName
= line
.substring(0, index
).trim();
341 position
= line
.substring(index
+ 1, line
.length() - 1);
344 Node tmpPerson
= createDraftNode(tmpParent
, PeopleTypes
.PEOPLE_PERSON
);
345 tmpPerson
.setProperty(PEOPLE_FIRST_NAME
, firstName
);
346 if (EclipseUiUtils
.notEmpty(lastName
))
347 tmpPerson
.setProperty(PEOPLE_LAST_NAME
, lastName
);
348 Node newPersonNode
= peopleService
.createEntity(targetParent
, PeopleTypes
.PEOPLE_PERSON
, tmpPerson
);
349 // if (EclipseUiUtils.notEmpty(position))
350 PersonJcrUtils
.addJob(resourcesService
, peopleService
, newPersonNode
, newOrgNode
, position
, true);
351 // Save the newly created entity without creating a base version
352 newPersonNode
= peopleService
.saveEntity(newPersonNode
, false);
357 private void importUrls(Node contactable
, String urlStr
) throws RepositoryException
{
358 String
[] urls
= urlStr
.split("\\n");
359 boolean hasPrimary
= false;
360 boolean hasPrimaryFacebook
= false;
362 loop
: for (String line
: urls
) {
363 if (EclipseUiUtils
.isEmpty(line
))
367 if (line
.startsWith("https://www.facebook.com")) {
368 PeopleJcrUtils
.createSocialMedia(resourcesService
, peopleService
, contactable
, line
,
369 !hasPrimaryFacebook
, ContactValueCatalogs
.CONTACT_CAT_FACEBOOK
, null);
370 hasPrimaryFacebook
= true;
372 PeopleJcrUtils
.createWebsite(resourcesService
, peopleService
, contactable
, line
, !hasPrimary
, null);
378 private void importMails(Node contactable
, String mailStr
) throws RepositoryException
{
379 String
[] urls
= mailStr
.split("\\n");
380 boolean hasPrimary
= false;
381 loop
: for (String line
: urls
) {
382 if (EclipseUiUtils
.isEmpty(line
))
385 PeopleJcrUtils
.createEmail(resourcesService
, peopleService
, contactable
, line
, !hasPrimary
, null, null);
390 // TODO make this configurable
391 int displayNameIndex
= 0;
392 int legalNameIndex
= 1;
393 int legalFormIndex
= 2;
396 int postalCodeIndex
= 5;
401 int telephoneNumberIndex
= 10;
403 int contactsIndex
= 12;
404 int descriptionIndex
= 13;
407 private Node
importDefaultOrgFile(InputStream in
) throws IOException
{
408 Session session
= null;
411 Workbook wb
= JxlUtils
.toWorkbook(in
, IMPORT_ENCODING
);
412 session
= repository
.login();
413 String basePath
= "/" + peopleService
.getBaseRelPath(PeopleTypes
.PEOPLE_ORG
);
414 Node targetParent
= session
.getNode(basePath
);
415 Sheet sheet
= wb
.getSheet(0);
417 Node tmpParent
= peopleService
.getDraftParent(session
);
419 int rowNb
= sheet
.getRows();
420 for (i
= 1; i
< rowNb
- 1; i
++) {
422 Node tmpOrg
= createDraftNode(tmpParent
, PeopleTypes
.PEOPLE_ORG
);
424 String dName
= JxlUtils
.getStringValue(sheet
, displayNameIndex
, i
);
426 tmpOrg
.setProperty(PeopleNames
.PEOPLE_DISPLAY_NAME
, dName
);
427 String lName
= getStringValue(sheet
, legalNameIndex
, i
);
429 tmpOrg
.setProperty(PeopleNames
.PEOPLE_LEGAL_NAME
, lName
);
430 String lForm
= getStringValue(sheet
, legalFormIndex
, i
);
432 tmpOrg
.setProperty(PeopleNames
.PEOPLE_LEGAL_FORM
, lForm
);
433 String urlStr
= getStringValue(sheet
, urlsIndex
, i
);
434 if (notEmpty(urlStr
))
435 importUrls(tmpOrg
, urlStr
);
436 String mailStr
= getStringValue(sheet
, mailIndex
, i
);
437 if (notEmpty(mailStr
))
438 importMails(tmpOrg
, mailStr
);
439 String streetStr
= getStringValue(sheet
, streetIndex
, i
);
440 String pcStr
= getStringValue(sheet
, postalCodeIndex
, i
);
441 String lStr
= getStringValue(sheet
, lIndex
, i
);
442 String stStr
= getStringValue(sheet
, stIndex
, i
);
443 String cStr
= getStringValue(sheet
, cIndex
, i
);
444 if (notEmpty(streetStr
) || notEmpty(pcStr
) || notEmpty(lStr
) || notEmpty(stStr
) || notEmpty(cStr
))
445 PeopleJcrUtils
.createAddress(resourcesService
, peopleService
, tmpOrg
, streetStr
, null, pcStr
, lStr
,
446 stStr
, cStr
, true, ContactValueCatalogs
.CONTACT_CAT_MAIN
, null);
447 String mobileStr
= getStringValue(sheet
, mobileIndex
, i
);
448 if (notEmpty(mobileStr
))
449 PeopleJcrUtils
.createPhone(resourcesService
, peopleService
, tmpOrg
, mobileStr
, true, null, null);
450 String phoneStr
= getStringValue(sheet
, telephoneNumberIndex
, i
);
451 if (notEmpty(phoneStr
))
452 PeopleJcrUtils
.createPhone(resourcesService
, peopleService
, tmpOrg
, phoneStr
, true,
453 ContactValueCatalogs
.CONTACT_CAT_DIRECT
, null);
454 String descStr
= getStringValue(sheet
, descriptionIndex
, i
);
455 if (notEmpty(descStr
))
456 tmpOrg
.setProperty(Property
.JCR_DESCRIPTION
, descStr
);
457 String tagsStr
= getStringValue(sheet
, tagsIndex
, i
);
458 if (notEmpty(tagsStr
))
459 tmpOrg
.setProperty(ResourcesNames
.CONNECT_TAGS
, ConnectJcrUtils
.parseAndClean(tagsStr
, ",", true));
461 Node newOrgNode
= peopleService
.createEntity(targetParent
, PeopleTypes
.PEOPLE_ORG
, tmpOrg
);
462 // Save the newly created entity without creating a base version
463 newOrgNode
= peopleService
.saveEntity(newOrgNode
, false);
465 String contactsStr
= getStringValue(sheet
, contactsIndex
, i
);
466 if (notEmpty(contactsStr
))
467 importOrgEmployees(tmpParent
, targetParent
, newOrgNode
, contactsStr
);
470 // Refresh tags and mailing list
471 Node tagParent
= resourcesService
.getTagLikeResourceParent(session
, ConnectConstants
.RESOURCE_TAG
);
472 resourcesService
.refreshKnownTags(tagParent
);
474 // Create Mailing lists
475 Node mlParent
= resourcesService
.getTagLikeResourceParent(session
, PeopleTypes
.PEOPLE_MAILING_LIST
);
476 resourcesService
.refreshKnownTags(mlParent
);
478 } catch (PeopleException
| RepositoryException e
) {
479 throw new SuiteException("Cannot import mapping file, error at line: " + (i
+ 1), e
);
481 JcrUtils
.logoutQuietly(session
);
487 /* DEPENDENCY INJECTION */
488 public void setRepository(Repository repository
) {
489 this.repository
= repository
;
492 public void setResourcesService(ResourcesService resourcesService
) {
493 this.resourcesService
= resourcesService
;
496 public void setPeopleService(PeopleService peopleService
) {
497 this.peopleService
= peopleService
;