import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.part.EditorPart;
+import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
+import eu.etaxonomy.cdm.api.service.molecular.ISequenceService;
import eu.etaxonomy.cdm.model.media.MediaUtils;
import eu.etaxonomy.cdm.model.molecular.Sequence;
import eu.etaxonomy.cdm.model.molecular.SequenceString;
import eu.etaxonomy.cdm.model.molecular.SingleReadAlignment;
import eu.etaxonomy.taxeditor.editor.handler.ToggleInsertOverwriteHandler;
import eu.etaxonomy.taxeditor.editor.handler.ToggleLeftRightInsertionHandler;
+import eu.etaxonomy.taxeditor.editor.view.derivate.DerivateViewEditorInput;
+import eu.etaxonomy.taxeditor.store.CdmStore;
*/
public class AlignmentEditor extends EditorPart {
public static final String ID = "eu.etaxonomy.taxeditor.editor.molecular.AlignmentEditor";
+
+ private final ConversationHolder conversationHolder;
+
public static final int READS_AREA_INDEX = 1;
public static final int CONSENSUS_AREA_INDEX = READS_AREA_INDEX + 1;
public static final int PHEROGRAM_AREA_INDEX = 0;
public static final String DEFAULT_READ_NAME_PREFIX = "Read ";
public static final String CONSENSUS_NAME = "Consensus";
-
+
private final SequenceDataChangeListener DIRTY_LISTENER = new SequenceDataChangeListener() {
@Override
public <T> void afterTokenChange(TokenChangeEvent<T> e) {
setDirty();
}
-
+
@Override
public <T> void afterSequenceRenamed(SequenceRenamedEvent<T> e) {
setDirty();
}
-
+
@Override
public <T> void afterSequenceChange(SequenceChangeEvent<T> e) {
setDirty();
}
-
+
@Override
public <T, U> void afterProviderChanged(SequenceDataProvider<T> oldProvider,
SequenceDataProvider<U> newProvider) { // Not expected.
-
+
setDirty();
}
};
-
+
private MultipleAlignmentsContainer alignmentsContainer = null;
- private Map<Integer, SingleReadAlignment> cdmMap = new TreeMap<Integer, SingleReadAlignment>(); //TODO Move this to ContigSequenceDataProvider
+ private final Map<Integer, SingleReadAlignment> cdmMap = new TreeMap<Integer, SingleReadAlignment>(); //TODO Move this to ContigSequenceDataProvider
private boolean dirty = false;
+ public AlignmentEditor() {
+ conversationHolder = CdmStore.createConversation();
+ }
+
private void refreshToolbarElement(String id) {
- ICommandService commandService =
+ ICommandService commandService =
(ICommandService)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getService(ICommandService.class);
if (commandService != null) {
commandService.refreshElements(id, Collections.EMPTY_MAP);
- }
+ }
}
-
+
private void registerEditSettingListener(MultipleAlignmentsContainer container) {
container.getEditSettings().addListener(new EditSettingsListener() {
@Override
public void workingModeChanged(EditSettingsChangeEvent e) {} // Currently nothing to do
-
+
@Override
public void insertLeftInDataAreaChanged(EditSettingsChangeEvent e) {
updateStatusBar();
refreshToolbarElement(ToggleLeftRightInsertionHandler.COMMAND_ID);
}
-
+
@Override
public void insertChanged(EditSettingsChangeEvent e) {
updateStatusBar();
}
});
}
-
-
+
+
private AlignmentArea createIndexArea(MultipleAlignmentsContainer container) {
AlignmentArea result = new AlignmentArea(container);
result.setAllowVerticalScrolling(false);
result.getDataAreas().getTopAreas().add(new SequenceIndexArea(result.getContentArea()));
return result;
}
-
-
+
+
private AlignmentArea createEditableAlignmentArea(MultipleAlignmentsContainer container, boolean allowVerticalScrolling) {
AlignmentArea result = new AlignmentArea(container);
result.setAllowVerticalScrolling(allowVerticalScrolling);
SequenceDataProvider<NucleotideCompound> provider = new PackedSequenceDataProvider<NucleotideCompound>(tokenSet);
result.setSequenceProvider(provider, false);
provider.getChangeListeners().add(DIRTY_LISTENER);
-
+
return result;
}
-
- private AlignmentArea createConsensusHintArea(MultipleAlignmentsContainer container,
+
+ private AlignmentArea createConsensusHintArea(MultipleAlignmentsContainer container,
SequenceDataProvider<?> sequenceProvider) {
-
+
AlignmentArea result = new AlignmentArea(container);
result.setAllowVerticalScrolling(false);
result.getDataAreas().getBottomAreas().add(
new ConsensusSequenceArea(result.getContentArea(), sequenceProvider));
return result;
}
-
-
+
+
private MultipleAlignmentsContainer getAlignmentsContainer() {
if (alignmentsContainer == null) {
alignmentsContainer = new MultipleAlignmentsContainer();
-
+
AlignmentAreaList list = alignmentsContainer.getAlignmentAreas();
list.add(createIndexArea(alignmentsContainer));
AlignmentArea readsArea = createEditableAlignmentArea(alignmentsContainer, true);
list.add(readsArea); // Make sure READS_AREA_INDEX is correct.
list.add(createEditableAlignmentArea(alignmentsContainer, false)); // Make sure COMSENSUS_AREA_INDEX is correct.
- list.add(createConsensusHintArea(alignmentsContainer,
+ list.add(createConsensusHintArea(alignmentsContainer,
readsArea.getSequenceProvider()));
-
+
registerEditSettingListener(alignmentsContainer);
}
return alignmentsContainer;
}
-
-
+
+
private AlignmentArea getReadsArea() {
return getAlignmentsContainer().getAlignmentAreas().get(READS_AREA_INDEX);
}
private AlignmentArea getConsensusArea() {
return getAlignmentsContainer().getAlignmentAreas().get(CONSENSUS_AREA_INDEX);
}
-
-
+
+
private PherogramArea getPherogramArea(int sequenceID) {
return (PherogramArea)getReadsArea().getDataAreas().getSequenceAreas(sequenceID).get(PHEROGRAM_AREA_INDEX);
}
-
-
+
+
private void createTestContents() {
// Just for testing:
try {
addRead(new File("D:/Users/BenStoever/Documents/Studium/Projekte/Promotion/EDITor/Quelltexte/LibrAlign branch/Repository/eu.etaxonomy.taxeditor.editor/src/main/resources/AlignmentTestData/JR430_JR-P01.ab1").toURI(), false);
addRead(new File("D:/Users/BenStoever/Documents/Studium/Projekte/Promotion/EDITor/Quelltexte/LibrAlign branch/Repository/eu.etaxonomy.taxeditor.editor/src/main/resources/AlignmentTestData/JR444_JR-P05.ab1").toURI(), false);
-
+
// Add test consensus sequence:
SequenceDataProvider consensusProvider = getConsensusArea().getSequenceProvider();
int id = consensusProvider.addSequence(CONSENSUS_NAME);
}
- private void readCDMData() {
+ private void readCDMData(Sequence sequenceNode) {
//TODO If called from somewhere else than createPartControl() the editorInput needs to be checked and previous contents need to be cleared (or updated).
- Sequence sequenceNode = ((AlignmentEditorInput)getEditorInput()).getSequenceNode();
-
+
// Add reads:
for (SingleReadAlignment singleReadAlignment : sequenceNode.getSingleReadAlignments()) {
try {
SingleRead pherogramInfo = singleReadAlignment.getSingleRead();
int id = addRead(pherogramInfo.getPrimer().getLabel(), //TODO Should the sequence name contain other/additional/alternative data? Can the same string as in the derivative tree be used here?
MediaUtils.getFirstMediaRepresentationPart(pherogramInfo.getPherogram()).getUri(),
- singleReadAlignment.isReverseComplement(),
- singleReadAlignment.getEditedSequence(),
+ singleReadAlignment.isReverseComplement(),
+ singleReadAlignment.getEditedSequence(),
singleReadAlignment.getShifts());
cdmMap.put(id, singleReadAlignment);
}
e.printStackTrace(); //TODO Output to user (Possibly collect for all pherograms and display in the end.)
}
}
-
+
// Set consensus sequence:
SequenceDataProvider consensusProvider = getConsensusArea().getSequenceProvider();
int id = consensusProvider.addSequence(CONSENSUS_NAME);
sequenceNode.getConsensusSequence().getString(), consensusProvider.getTokenSet()));
//TODO Can the consensus sequence also be null? / Should it be created here, if nothing is in the DB?
}
-
-
+
+
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
public void createPartControl(Composite parent) {
getAlignmentsContainer().createSWTWidget(parent, SWT.NONE);
updateStatusBar();
-
+
if (getEditorInput() instanceof AlignmentEditorInput) {
if (((AlignmentEditorInput)getEditorInput()).getSequenceNode() != null) {
- readCDMData();
+ Sequence sequenceNode = ((AlignmentEditorInput)getEditorInput()).getSequenceNode();
+ //re-load into the current session if it is already persisted in the DB
+ if(sequenceNode!=null && sequenceNode.getId()!=0){
+ sequenceNode = CdmStore.getService(ISequenceService.class).load(sequenceNode.getUuid());
+ }
+ readCDMData(sequenceNode);
}
else {
createTestContents(); // This case will removed after the test phase and an exception should probably be thrown.
}
}
else {
- throw new IllegalArgumentException("The editor input must have the type " +
+ throw new IllegalArgumentException("The editor input must have the type " +
AlignmentEditorInput.class.getCanonicalName()); //TODO What should be done here?
}
}
-
-
+
+
private void updateStatusBar() {
IActionBars bars = getEditorSite().getActionBars();
- bars.getStatusLineManager().setMessage("Edit mode: " +
+ bars.getStatusLineManager().setMessage("Edit mode: " +
(getReadsArea().getEditSettings().isInsert() ? "Insert" : "Overwrite") + " " +
"Insertion in pherogram: " +
(getReadsArea().getEditSettings().isInsertLeftInDataArea() ? "Left" : "Right"));
}
-
+
private SingleReadAlignment.Shift[] convertToCDMShifts(PherogramAlignmentModel alignmentModel) {
SingleReadAlignment.Shift[] result = new SingleReadAlignment.Shift[alignmentModel.getShiftChangeCount()];
Iterator<ShiftChange> iterator = alignmentModel.shiftChangeIterator();
}
return result;
}
-
-
+
+
/* (non-Javadoc)
* @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
*/
System.out.println("save 2");
Sequence sequenceNode = ((AlignmentEditorInput)getEditorInput()).getSequenceNode();
StringAdapter stringProvider = new StringAdapter(getConsensusArea().getSequenceProvider(), false); // Throws an exception if a token has more than one character.
-
+
// Write consensus sequence:
SequenceString consensusSequenceObj = sequenceNode.getConsensusSequence();
String newConsensusSequence = stringProvider.getSequence(
else {
consensusSequenceObj.setString(newConsensusSequence);
}
-
+
// Write single reads:
stringProvider.setUnderlyingProvider(getReadsArea().getSequenceProvider());
sequenceNode.getSingleReadAlignments().retainAll(cdmMap.values()); // Remove all reads that are not in the alignment anymore.
//TODO Create new read object. => Shall it be allowed to add reads in the alignment editor which are not represented in the CDM tree before the alignment editor is saved?
//singleRead = SingleReadAlignment.NewInstance(consensusSequence, singleRead, shifts, editedSequence);
}
-
+
singleRead.setEditedSequence(stringProvider.getSequence(id));
singleRead.setReverseComplement(getPherogramArea(id).getProvider() instanceof ReverseComplementPherogramProvider); // Works only if ReverseComplementPherogramProvider instances are not nested.
singleRead.setShifts(convertToCDMShifts(getPherogramArea(id).getAlignmentModel()));
System.out.println(singleRead.getShifts());
}
}
- dirty = false; //TODO "*" is not removed from editor title. Why not? (Should be save action in the tool bar be disabled when isDirty() returns false? This is also not the case.)
+
+ String taskName = "Saving alignment";
+ monitor.beginTask(taskName, 3);
+ if (!conversationHolder.isBound()) {
+ conversationHolder.bind();
+ }
+ monitor.worked(1);
+
+ // commit the conversation and start a new transaction immediately
+ conversationHolder.commit(true);
+ monitor.worked(1);
+
+ dirty = false; //TODO "*" is not removed from editor title. Why not? (Should be save action in the tool bar be disabled when isDirty() returns false? This is also not the case.)
+ monitor.worked(1);
+ monitor.done();
+ firePropertyChange(PROP_DIRTY);
}
-
+
/* (non-Javadoc)
* @see org.eclipse.ui.part.EditorPart#doSaveAs()
*/
@Override
public void doSaveAs() {}
-
+
/* (non-Javadoc)
* @see org.eclipse.ui.part.EditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
setSite(site);
setInput(input);
}
-
+
/* (non-Javadoc)
* @see org.eclipse.ui.part.EditorPart#isDirty()
public boolean isDirty() {
return dirty;
}
-
-
+
+
private void setDirty() {
dirty = true;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
public boolean isSaveAsAllowed() {
return false; // "Save as" not allowed.
}
-
+
@Override
- public void setFocus() {}
+ public void setFocus() {
+ if(conversationHolder!=null){
+ conversationHolder.bind();
+ }
+ }
+
-
public boolean isInsertMode() {
return getAlignmentsContainer().getEditSettings().isInsert();
}
-
+
public boolean isInsertLeftInPherogram() {
return getAlignmentsContainer().getEditSettings().isInsertLeftInDataArea();
}
-
-
+
+
public void toggleLeftRightInsertionInPherogram() {
getAlignmentsContainer().getEditSettings().toggleInsertLeftInDataArea();
}
-
+
public void toggleInsertOverwrite() {
getAlignmentsContainer().getEditSettings().toggleInsert();
}
-
-
+
+
public static PherogramProvider readPherogram(URI uri) throws IOException, UnsupportedChromatogramFormatException {
PherogramProvider result;
InputStream stream = uri.toURL().openStream();
return result;
}
-
+
private String newReadName() {
int index = 1;
- while (getReadsArea().getSequenceProvider().sequenceIDByName(DEFAULT_READ_NAME_PREFIX + index)
+ while (getReadsArea().getSequenceProvider().sequenceIDByName(DEFAULT_READ_NAME_PREFIX + index)
!= SequenceDataProvider.NO_SEQUENCE_FOUND) {
-
+
index++;
}
return DEFAULT_READ_NAME_PREFIX + index;
}
-
+
public void addRead(URI pherogramURI, boolean reverseComplemented) throws IOException, UnsupportedChromatogramFormatException {
addRead(newReadName(), pherogramURI, reverseComplemented, null, null);
}
-
-
+
+
/**
* Adds a new sequence with attached phergram data area to the reads alignment.
* <p>
* If {@code null} is specified as {@code editedSequence} the base call sequence from the pherogram will
* be set as the edited sequence. If {@code null} is specified as {@code shifts} no shifts between the edited
* and the base calls sequence are assumed.
- *
+ *
* @param name the name of the new sequence
* @param pherogramURI the URI where the associated pherogram file is located
- * @param reverseComplemented Specify {@code true} here, if the reverse complement of the pherogram data should
+ * @param reverseComplemented Specify {@code true} here, if the reverse complement of the pherogram data should
* be added, {@code false} otherwise.
* @param editedSequence the edited version of the base call sequence (May be {@code null}.)
* @param shifts the alignment information that links the edited and the base call sequence (May be {@code null}.)
* @throws IOException if an error occurred when trying to read the pherogram file
* @throws UnsupportedChromatogramFormatException if the format of the pherogram file is not supported
*/
- public int addRead(String name, URI pherogramURI, boolean reverseComplemented, String editedSequence,
+ public int addRead(String name, URI pherogramURI, boolean reverseComplemented, String editedSequence,
SingleReadAlignment.Shift[] shifts) throws IOException, UnsupportedChromatogramFormatException {
-
+
SequenceDataProvider provider = getReadsArea().getSequenceProvider();
PherogramProvider pherogramProvider = readPherogram(pherogramURI); // Must happen before a sequence is added, because it might throw an exception.
if (reverseComplemented) {
pherogramProvider = new ReverseComplementPherogramProvider(pherogramProvider);
}
-
+
// Create sequence:
provider.addSequence(name);
int id = provider.sequenceIDByName(name);
-
- // Set edited sequence:
+
+ // Set edited sequence:
Collection<Object> tokens; // First save tokens in a collection to avoid GUI updated for each token.
if (editedSequence != null) {
tokens = SequenceUtils.stringToTokenList(editedSequence, provider.getTokenSet());
setDirty();
}
provider.insertTokensAt(id, 0, tokens);
-
+
// Create pherogram area:
PherogramArea pherogramArea = new PherogramArea(getReadsArea().getContentArea(), pherogramProvider);
}
setDirty();
}
-
+
// Add pherogram area to GUI:
pherogramArea.addMouseListener(new PherogramMouseListener(pherogramURI));
getReadsArea().getDataAreas().getSequenceAreas(id).add(pherogramArea);
-
+
// Save source URI:
return id;
}