uk.ac.ebi.mnb.dialog.file.NewReaction.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.ebi.mnb.dialog.file.NewReaction.java

Source

/*
 * Copyright (c) 2013. EMBL, European Bioinformatics Institute
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package uk.ac.ebi.mnb.dialog.file;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
import com.jgoodies.forms.layout.Sizes;
import mnb.io.tabular.NamedEntityResolver;
import mnb.io.tabular.parser.ReactionParser;
import mnb.io.tabular.parser.UnparsableReactionError;
import mnb.io.tabular.preparse.PreparsedReaction;
import mnb.io.tabular.type.ReactionColumn;
import org.apache.log4j.Logger;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import uk.ac.ebi.caf.component.ReplacementHandler;
import uk.ac.ebi.caf.component.SuggestionField;
import uk.ac.ebi.caf.component.SuggestionHandler;
import uk.ac.ebi.caf.component.factory.LabelFactory;
import uk.ac.ebi.caf.report.ReportManager;
import uk.ac.ebi.mdk.domain.entity.AnnotatedEntity;
import uk.ac.ebi.mdk.domain.entity.DefaultEntityFactory;
import uk.ac.ebi.mdk.domain.entity.Metabolite;
import uk.ac.ebi.mdk.domain.entity.Reconstruction;
import uk.ac.ebi.mdk.domain.entity.collection.DefaultReconstructionManager;
import uk.ac.ebi.mdk.domain.entity.collection.ReconstructionManager;
import uk.ac.ebi.mdk.domain.entity.reaction.Compartment;
import uk.ac.ebi.mdk.domain.entity.reaction.MetabolicReaction;
import uk.ac.ebi.mdk.domain.entity.reaction.compartment.Organelle;
import uk.ac.ebi.mdk.domain.identifier.Identifier;
import uk.ac.ebi.mdk.domain.identifier.basic.BasicReactionIdentifier;
import uk.ac.ebi.mdk.domain.tool.AutomaticCompartmentResolver;
import uk.ac.ebi.mdk.domain.tool.PrefixCompartmentResolver;
import uk.ac.ebi.mdk.tool.CompartmentResolver;
import uk.ac.ebi.metingear.edit.entity.AddEntitiesEdit;
import uk.ac.ebi.metingear.search.FieldType;
import uk.ac.ebi.metingear.search.SearchManager;
import uk.ac.ebi.metingear.search.SearchableIndex;
import uk.ac.ebi.mnb.core.EntityMap;
import uk.ac.ebi.mnb.core.ErrorMessage;
import uk.ac.ebi.mnb.interfaces.SelectionController;
import uk.ac.ebi.mnb.interfaces.TargetedUpdate;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author johnmay
 * @author $Author$ (this version)
 * @version $Rev$ : Last Changed $Date$
 * @name NewMetabolite - 2011.10.04 <br>
 * Class description
 */
public class NewReaction extends NewEntity {

    private static final Logger LOGGER = Logger.getLogger(NewReaction.class);
    private SuggestionField equation;
    private static CellConstraints cc = new CellConstraints();

    // stuff for lucene
    private static final String LUCENE_ESCAPE_CHARS = "[\\\\+\\-\\!\\(\\)\\:\\^\\[\\]\\{\\}\\~\\*\\?]";

    private static final Pattern LUCENE_PATTERN = Pattern.compile(LUCENE_ESCAPE_CHARS);

    private static final String REPLACEMENT_STRING = "\\\\$0";

    private TermQuery typeFilter = new TermQuery(FieldType.TYPE
            .getTerm(DefaultEntityFactory.getInstance().getRootClass(Metabolite.class).getSimpleName()));
    private static String[] fields = new String[] { FieldType.NAME.getName(), FieldType.ABBREVIATION.getName() };

    public NewReaction(JFrame frame, TargetedUpdate updater, ReportManager messages, SelectionController controller,
            UndoableEditListener undoableEdits) {
        super(frame, updater, messages, controller, undoableEdits);
        setDefaultLayout();
    }

    @Override
    public JLabel getDescription() {
        JLabel label = super.getDescription();
        label.setText("Please specify detail for a new reaction");
        return label;
    }

    @Override
    public JPanel getForm() {

        JPanel panel = super.getForm();

        equation = new SuggestionField(this, 5, new ReactionSuggestionHandler(), new ReplacementHandler());

        FormLayout layout = (FormLayout) panel.getLayout();
        layout.appendRow(new RowSpec(Sizes.DLUY4));
        layout.appendRow(new RowSpec(Sizes.PREFERRED));
        JLabel label = LabelFactory.newFormLabel("Reaction Equation",
                "Enter a text equation for your reaction (e.g. 1 A + B -> C [e])");
        label.setHorizontalAlignment(JLabel.LEADING);
        panel.add(label, cc.xyw(1, layout.getRowCount(), layout.getColumnCount()));
        layout.appendRow(new RowSpec(Sizes.DLUY4));
        layout.appendRow(new RowSpec(Sizes.PREFERRED));
        panel.add(equation, cc.xyw(1, layout.getRowCount(), layout.getColumnCount()));

        return panel;
    }

    @Override
    public Identifier getIdentifier() {
        return BasicReactionIdentifier.nextIdentifier();
    }

    @Override
    public void process() {

        ReconstructionManager manager = DefaultReconstructionManager.getInstance();
        if (manager.active() != null) {
            Reconstruction reconstruction = manager.active();

            ReactionParser parser = new ReactionParser(new NamedEntityResolver(),
                    new AutomaticCompartmentResolver());
            PreparsedReaction ppRxn = new PreparsedReaction();

            ppRxn.addValue(ReactionColumn.ABBREVIATION, getAbbreviation());
            ppRxn.addValue(ReactionColumn.DESCRIPTION, getName());
            ppRxn.addValue(ReactionColumn.EQUATION, equation.getText());

            try {
                MetabolicReaction reaction = parser.parseReaction(ppRxn);
                reaction.setIdentifier(getIdentifier());
                reconstruction.addReaction(reaction);
                AddEntitiesEdit edit = new AddEntitiesEdit(reconstruction,
                        EntityMap.singleton(DefaultEntityFactory.getInstance(), reaction));
                addEdit(edit);
            } catch (UnparsableReactionError ex) {
                addMessage(new ErrorMessage("Malformed reaction: " + ex.getMessage()));
            }

        }
    }

    private class ReactionSuggestionHandler extends SuggestionHandler {

        @Override
        public Collection<Object> getSuggestions(DocumentEvent e) {

            try {

                int[] range = expand(e);

                String input = e.getDocument().getText(e.getOffset(), e.getLength());
                String text = e.getDocument().getText(0, e.getDocument().getLength());

                if (input.equals("[")) {

                    List<Object> suggestions = new ArrayList<Object>();

                    // handle compartment auto-complete
                    for (Compartment compartment : Arrays.asList(Organelle.values())) {
                        suggestions.add(text + compartment.getAbbreviation() + "] ");
                    }

                    return suggestions;

                } else if (!input.matches("-|\\+|<|>|=")) {

                    if (range[0] != range[1]) {

                        String edit = text.substring(range[0], range[1]).trim();

                        if (edit.contains("[") && !edit.contains("]")) {
                            // do long compartment name prediction
                            CompartmentResolver resolver = new PrefixCompartmentResolver();
                            edit = edit.substring(Math.min(edit.indexOf('[') + 1, edit.length() - 1),
                                    edit.length());
                            List<Object> suggestions = new ArrayList<Object>();
                            for (Compartment compartment : resolver.getCompartments(edit)) {
                                suggestions.add(text.substring(0, text.indexOf('[', range[0]) + 1)
                                        + compartment.getDescription() + "] ");
                            }
                            return suggestions;
                        }

                        SearchableIndex index = SearchManager.getInstance().getCurrentIndex();

                        String searchableText = LUCENE_PATTERN.matcher(edit).replaceAll(REPLACEMENT_STRING);

                        Query baseQuery = SearchManager.getInstance().getQuery(fields, searchableText + "*~");

                        BooleanQuery query = new BooleanQuery();
                        query.add(baseQuery, BooleanClause.Occur.MUST);
                        query.add(typeFilter, BooleanClause.Occur.MUST);

                        List<AnnotatedEntity> entities = index.getRankedEntities(baseQuery, 25, Metabolite.class);

                        List<Object> suggestions = new ArrayList<Object>();

                        for (AnnotatedEntity entity : entities) {
                            suggestions.add(text.substring(0, range[0]) + entity.getName()
                                    + text.substring(range[1], text.length()));
                        }

                        return suggestions;

                    }

                } else {
                }

            } catch (BadLocationException e1) {
                e1.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
            } catch (ParseException e1) {
                e1.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
            } catch (IOException e1) {
                e1.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
            }

            return new ArrayList<Object>();
        }

        // expand the range of the edit to the current metabolite
        private int[] expand(DocumentEvent event) throws BadLocationException {

            Document document = event.getDocument();
            int offset = event.getOffset() + 1;
            String text = document.getText(0, document.getLength());

            for (int i = offset + 1; i >= 0; i--) {

                int start = Math.max(0, i - 1);
                int end = Math.min(start + (i > 0 ? 3 : 2), text.length());

                String substring = text.substring(start, end);

                // ends of field
                if (substring.length() == 3) {
                    if (substring.equals(" + ")) {
                        return end >= offset ? new int[] { offset, offset } : new int[] { end, offset };
                    } else if (substring.matches("<[ -=]>") || substring.matches("<[ -=]{2}")
                            || substring.matches("[ -=]{2}>") || substring.matches("<[ -=]{1}\\s")
                            || substring.matches("[ -=]{1}>\\s")) {
                        return end >= offset ? new int[] { offset, offset } : new int[] { end, offset };

                    }
                }
                // catches end cases
                else if (substring.length() == 2) {
                    if (((substring.equals("+ ") && i != offset && i + 1 != offset)
                            || (substring.equals(" +") && i != 0))) {
                        return new int[] { end, offset };
                    } else if (substring.matches("<[ -=]") || substring.matches("[ -=]>") || substring.matches(" <")
                            || substring.matches("> ")) {
                        return end >= offset ? new int[] { offset, offset } : new int[] { end, offset };
                    }
                }

            }

            return new int[] { 0, offset };

        }

    }

}