Post

3 followers Follow
0
Avatar

Import folder structures

I have an importer that import different kinds of files. Yet, it only works for single files and I want to adapt it to a whole folder. I used the function _importDocuments in each importer, but this function is never called. Possibly it is rejected before in getPermissibleExtensions() and tentativeAutoDetect.

 

How can I manage folders ?

VL

Please sign in to leave a comment.

13 comments

0
Avatar

As a user of Geneious, you can just select all the files in a folder and drag and drop them in as a group and Geneious should call your importer for each file. For Geneious R9, which will be released later this year, Geneious will have a folder import option which will automatically call your importer for each file in a folder chosen by the user. I recommend you wait until then, but if you really need folder import now, you will probably need to implement a DocumentOperation in your plugin that prompts the user for a folder and produces the documents as output from the operation.

Hilary Miller 0 votes
Comment actions Permalink
0
Avatar

Thank you. But as long it is unclear when a newer version will be released, I guess I better implement it on my own.
Unfortunenately, I am a newbie to Geneious Plugins and do not quite understand how I should integrate my importers in the DocumentOperation. I have several importer classes like MegAlign, PrimerSelection ,... importer in my class MyImporter extends GeneiousPlugin. I do not really understand where I should integrate DocumentOperation. As I read the doumentation it seems as if GeneiousGridImporter[] getImporter() would be the right function. But again this function is never called in MyImporter.

VL 0 votes
Comment actions Permalink
0
Avatar

Hi,

Ignore the grid classes. These are for running on networks of computers.

What you should do is implement GeneiousPlugin.getDocumentOperations() and define a DocumentOperation that requires no input and produces the documents you import as output. For example:

public DocumentOperation[] getDocumentOperations() {
DocumentOperation operation = new DocumentOperation() {
@Override
public GeneiousActionOptions getActionOptions() {
return new GeneiousActionOptions("My custom format from folder").setMainMenuLocation(GeneiousActionOptions.MainMenu.Import);
}

@Override
public String getHelp() {
return null;
}

@Override
public DocumentSelectionSignature[] getSelectionSignatures() {
return new DocumentSelectionSignature[0];
}

@Override
public void performOperation(AnnotatedPluginDocument[] annotatedDocuments, ProgressListener progressListener, Options options, SequenceSelection sequenceSelection, OperationCallback callback) throws DocumentOperationException {
callback.addDocument(new DefaultNucleotideSequence("a", "GATT"), false, ProgressListener.EMPTY);
}
};
return new DocumentOperation[]{operation};
}


You should fill in the details of performOperation to prompt the user for a folder and create the documents.

Hilary Miller 0 votes
Comment actions Permalink
0
Avatar

It works now. But ideally I also want to keep my subfolders. I couldn't find out how to create new folders in a given path and write files in specific folders.

Is it possible ?

 

VL 0 votes
Comment actions Permalink
0
Avatar

You can use callback.setSubFolder(), but that doesn't support nested sub-folders. So if you need sub folders more than 1 level deep, you could do something like this inside your performOperation method:

 

DefaultNucleotideSequence sequence = new DefaultNucleotideSequence("a", "GATT");
GeneiousService selectedService = ServiceUtilities.getSelectedService();
try {
if (selectedService instanceof WritableDatabaseService) {
WritableDatabaseService service = (WritableDatabaseService) selectedService;
service = service.createChildFolder("folderName").createChildFolder("subFolderName");
service.addDocumentCopy(DocumentUtilities.createAnnotatedPluginDocument(sequence),ProgressListener.EMPTY);
}
else {
callback.setSubFolder("folderName"); // This doesn't support sub-folders
callback.addDocument(sequence, false, ProgressListener.EMPTY);
}
} catch (DatabaseServiceException e) {
throw new DocumentOperationException(e);
}
Hilary Miller 0 votes
Comment actions Permalink
0
Avatar

If no folder is selected, another window pops up and asks for a destination folder. However I cannot get this new folder by  ServiceUtilities.getSelectedService(). I tried to call ServiceUtilities.getResultsDestination(), but it asks for a path for a second time... How can I either suppress the first popup window or getting the path of it?

VL 0 votes
Comment actions Permalink
0
Avatar

Once at the start of performOperation you should call ServiceUtilities.getSelectedService(). If that doesn't return a WritableDatabaseService then call ServiceUtilities.getResultsDestination(). Then import all your documents into to that service or child folders of it.

Hilary Miller 0 votes
Comment actions Permalink
0
Avatar

This is what I tried. But the popup window for destination selections is already displayed before performOperation. When I call ServiceUtilities.getResultsDestination() the selection window pop ups for a second time, although I already chose a folder. When I call ServiceUtilities.getResultsDestination() there is no problem and I get my destination folder. But this function is called before (I didn't call it somewhere else) and I cannot catch it.

This is what I got for performOperation:

 

public void performOperation(AnnotatedPluginDocument[] annotatedDocuments, ProgressListener progressListener, Options options, SequenceSelection sequenceSelection, OperationCallback callback) throws DocumentOperationException {

                // At this point ResultsDestination is already called
                options.getOptions();
                String pathname = options.getValueAsString("FolderToBeImported");
                File[] files = new File(pathname).listFiles();

                WritableDatabaseService service= (WritableDatabaseService) PluginUtilities.getGeneiousService("LocalDocuments");
                GeneiousService selectedService = ServiceUtilities.getSelectedService();
                if (!(selectedService instanceof WritableDatabaseService)) {
                    selectedService = ServiceUtilities.getResultsDestination();   // Here another ResultsDestination is called
               }
               
                for(File file: files){
                    service =  (WritableDatabaseService) selectedService;

                    try {
                       parentFolder = file.getParentFile().getName();
                       service = service.createChildFolder(parentFolder);

                    }catch{...}

            }

 

 

VL 0 votes
Comment actions Permalink
0
Avatar

Sorry, I didn't quite understand the problem initially. You can fix that by adding this to your DocumentOperation:

 

@Override
public boolean isDocumentGenerator() {
return false;
}
Hilary Miller 0 votes
Comment actions Permalink
0
Avatar

This fixed one problem, but actually I return a PluginDocument (TextDocument) in case my importer fails to import some documents. I used callback.addDocument(), but this does not work if I set this to false; As far I could figure out, the service does not support PluginDocuments but only AnnotatedPluginDocuments.

VL 0 votes
Comment actions Permalink
0
Avatar

When overriding isDocumentGenerator, you should ignore the callback and add all documents directly to the service. Any PluginDocument can be wrapped in an AnnotatedPluginDocument using DocumentUtilities.createAnnotatedPluginDocument().  

Hilary Miller 0 votes
Comment actions Permalink