From: BobHanson Date: Mon, 1 Jun 2020 21:10:28 +0000 (-0500) Subject: JAL-3626 Regex optimization from JAL-3253-applet; also minor X-Git-Url: http://source.jalview.org/gitweb/?p=jalview.git;a=commitdiff_plain;h=76821e9f28923b6f3ae8f226e01d0156e7b7f847;ds=sidebyside JAL-3626 Regex optimization from JAL-3253-applet; also minor StockholmFile for loop opt. --- diff --git a/src/jalview/analysis/Finder.java b/src/jalview/analysis/Finder.java index 3cbef6d..f21d7da 100644 --- a/src/jalview/analysis/Finder.java +++ b/src/jalview/analysis/Finder.java @@ -31,6 +31,7 @@ import jalview.datamodel.SequenceGroup; import jalview.datamodel.SequenceI; import jalview.datamodel.VisibleContigsIterator; import jalview.util.Comparison; +import jalview.util.Platform; import java.util.List; import java.util.Vector; @@ -129,7 +130,7 @@ public class Finder implements FinderI { String searchString = matchCase ? theSearchString : theSearchString.toUpperCase(); - Regex searchPattern = new Regex(searchString); + Regex searchPattern = Platform.newRegex(searchString); searchPattern.setIgnoreCase(!matchCase); searchResults = new SearchResults(); diff --git a/src/jalview/analysis/ParseProperties.java b/src/jalview/analysis/ParseProperties.java index 4b68d93..bfd4d6a 100644 --- a/src/jalview/analysis/ParseProperties.java +++ b/src/jalview/analysis/ParseProperties.java @@ -23,6 +23,7 @@ package jalview.analysis; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; +import jalview.util.Platform; import com.stevesoft.pat.Regex; @@ -90,7 +91,7 @@ public class ParseProperties String[] ScoreDescriptions, String regex, boolean repeat) { int count = 0; - Regex pattern = new Regex(regex); + Regex pattern = Platform.newRegex(regex); if (pattern.numSubs() > ScoreNames.length) { // Check that we have enough labels and descriptions for any parsed diff --git a/src/jalview/ext/ensembl/EnsemblCdna.java b/src/jalview/ext/ensembl/EnsemblCdna.java index e01ad17..ec7318f 100644 --- a/src/jalview/ext/ensembl/EnsemblCdna.java +++ b/src/jalview/ext/ensembl/EnsemblCdna.java @@ -23,6 +23,7 @@ package jalview.ext.ensembl; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; import jalview.io.gff.SequenceOntologyI; +import jalview.util.Platform; import java.util.ArrayList; import java.util.List; @@ -44,7 +45,7 @@ public class EnsemblCdna extends EnsemblSeqProxy * or ENSMUST or similar for other species * or CCDSnnnnn.nn with at least 3 digits */ - private static final Regex ACCESSION_REGEX = new Regex( + private static final Regex ACCESSION_REGEX = Platform.newRegex( "(ENS([A-Z]{3}|)[TG][0-9]{11}$)" + "|" + "(CCDS[0-9.]{3,}$)"); /* diff --git a/src/jalview/ext/ensembl/EnsemblGene.java b/src/jalview/ext/ensembl/EnsemblGene.java index 0e3d84b..157b8b9 100644 --- a/src/jalview/ext/ensembl/EnsemblGene.java +++ b/src/jalview/ext/ensembl/EnsemblGene.java @@ -55,7 +55,7 @@ public class EnsemblGene extends EnsemblSeqProxy * accepts anything as we will attempt lookup of gene or * transcript id or gene name */ - private static final Regex ACCESSION_REGEX = new Regex(".*"); + private static final Regex ACCESSION_REGEX = Platform.newRegex(".*"); private static final EnsemblFeatureType[] FEATURES_TO_FETCH = { EnsemblFeatureType.gene, EnsemblFeatureType.transcript, diff --git a/src/jalview/ext/ensembl/EnsemblProtein.java b/src/jalview/ext/ensembl/EnsemblProtein.java index 0280f16..468f05d 100644 --- a/src/jalview/ext/ensembl/EnsemblProtein.java +++ b/src/jalview/ext/ensembl/EnsemblProtein.java @@ -23,6 +23,7 @@ package jalview.ext.ensembl; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.util.Platform; import java.util.ArrayList; import java.util.List; @@ -42,7 +43,7 @@ public class EnsemblProtein extends EnsemblSeqProxy * or ENSMUSP or similar for other species * or CCDSnnnnn.nn with at least 3 digits */ - private static final Regex ACCESSION_REGEX = new Regex( + private static final Regex ACCESSION_REGEX = Platform.newRegex( "(ENS([A-Z]{3}|)P[0-9]{11}$)" + "|" + "(CCDS[0-9.]{3,}$)"); /** diff --git a/src/jalview/ext/ensembl/EnsemblSequenceFetcher.java b/src/jalview/ext/ensembl/EnsemblSequenceFetcher.java index 7454eb6..2008fb6 100644 --- a/src/jalview/ext/ensembl/EnsemblSequenceFetcher.java +++ b/src/jalview/ext/ensembl/EnsemblSequenceFetcher.java @@ -23,6 +23,7 @@ package jalview.ext.ensembl; import jalview.analysis.AlignmentUtils; import jalview.bin.Cache; import jalview.datamodel.DBRefSource; +import jalview.util.Platform; import jalview.ws.seqfetcher.DbSourceProxyImpl; import com.stevesoft.pat.Regex; @@ -50,7 +51,7 @@ abstract class EnsemblSequenceFetcher extends DbSourceProxyImpl * or ENSMUSP or similar for other species * or CCDSnnnnn.nn with at least 3 digits */ - private static final Regex ACCESSION_REGEX = new Regex( + private static final Regex ACCESSION_REGEX = Platform.newRegex( "(ENS([A-Z]{3}|)[GTEP]{1}[0-9]{11}$)" + "|" + "(CCDS[0-9.]{3,}$)"); diff --git a/src/jalview/io/ModellerDescription.java b/src/jalview/io/ModellerDescription.java index a56f2af..48a6903 100755 --- a/src/jalview/io/ModellerDescription.java +++ b/src/jalview/io/ModellerDescription.java @@ -22,6 +22,7 @@ package jalview.io; import jalview.datamodel.DBRefEntry; import jalview.datamodel.SequenceI; +import jalview.util.Platform; import java.util.List; @@ -95,12 +96,20 @@ public class ModellerDescription } }; + private static Regex VALIDATION_REGEX; + + private static Regex getRegex() + { + return (VALIDATION_REGEX == null + ? VALIDATION_REGEX = Platform + .newRegex("\\s*((([-0-9]+).?)|FIRST|LAST|@)", null) + : VALIDATION_REGEX); + } + private resCode validResidueCode(String field) { Integer val = null; - Regex r = new Regex( - "\\s*((([-0-9]+).?)|FIRST|LAST|@)"); - + Regex r = getRegex(); if (!r.search(field)) { return null; // invalid diff --git a/src/jalview/io/NewickFile.java b/src/jalview/io/NewickFile.java index f3eaa45..ea31e67 100755 --- a/src/jalview/io/NewickFile.java +++ b/src/jalview/io/NewickFile.java @@ -28,6 +28,7 @@ package jalview.io; import jalview.datamodel.SequenceNode; import jalview.util.MessageManager; +import jalview.util.Platform; import java.io.BufferedReader; import java.io.File; @@ -37,6 +38,8 @@ import java.util.StringTokenizer; import com.stevesoft.pat.Regex; +// TODO This class does not conform to Java standards for field name capitalization. + /** * Parse a new hanpshire style tree Caveats: NHX files are NOT supported and the * tree distances and topology are unreliable when they are parsed. TODO: on @@ -76,7 +79,7 @@ import com.stevesoft.pat.Regex; */ public class NewickFile extends FileParse { - SequenceNode root; + private SequenceNode root; private boolean HasBootstrap = false; @@ -85,21 +88,90 @@ public class NewickFile extends FileParse private boolean RootHasDistance = false; // File IO Flags - boolean ReplaceUnderscores = false; + private boolean ReplaceUnderscores = false; + + private boolean printRootInfo = true; + + private static final int REGEX_PERL_NODE_REQUIRE_QUOTE = 0; + + private static final int REGEX_PERL_NODE_ESCAPE_QUOTE = 1; + + private static final int REGEX_PERL_NODE_UNQUOTED_WHITESPACE = 2; + + private static final int REGEX_MAJOR_SYMS = 3; + + private static final int REGEX_QNODE_NAME = 4; + + private static final int REGEX_COMMENT = 5; + + private static final int REGEX_UQNODE_NAME = 6; - boolean printRootInfo = true; + private static final int REGEX_NBOOTSTRAP = 7; + + private static final int REGEX_NDIST = 8; + + private static final int REGEX_NO_LINES = 9; + + private static final int REGEX_PERL_EXPAND_QUOTES = 10; + + private static final int REGEX_MAX = 11; + + private static final Regex[] REGEX = new Regex[REGEX_MAX]; + + private static Regex getRegex(int id) + { + if (REGEX[id] == null) + { + String code = null; + String code2 = null; + String codePerl = null; + switch (id) + { + case REGEX_PERL_NODE_REQUIRE_QUOTE: + codePerl = "m/[\\[,:'()]/"; + break; + case REGEX_PERL_NODE_ESCAPE_QUOTE: + codePerl = "s/'/''/"; + break; + case REGEX_PERL_NODE_UNQUOTED_WHITESPACE: + codePerl = "s/\\/w/_/"; + break; + case REGEX_PERL_EXPAND_QUOTES: + codePerl = "s/''/'/"; + break; + case REGEX_MAJOR_SYMS: + code = "[(\\['),;]"; + break; + case REGEX_QNODE_NAME: + code = "'([^']|'')+'"; + break; + case REGEX_COMMENT: + code = "]"; + break; + case REGEX_UQNODE_NAME: + code = "\\b([^' :;\\](),]+)"; + break; + case REGEX_NBOOTSTRAP: + code = "\\s*([0-9+]+)\\s*:"; + break; + case REGEX_NDIST: + code = ":([-0-9Ee.+]+)"; + break; + case REGEX_NO_LINES: + code = "\n+"; + code2 = ""; + break; + default: + return null; + } + return codePerl == null ? Platform.newRegex(code, code2) + : Platform.newRegexPerl(codePerl); + } + return REGEX[id]; + } - private Regex[] NodeSafeName = new Regex[] { - new Regex().perlCode("m/[\\[,:'()]/"), // test for - // requiring - // quotes - new Regex().perlCode("s/'/''/"), // escaping quote - // characters - new Regex().perlCode("s/\\/w/_/") // unqoted whitespace - // transformation - }; - char QuoteChar = '\''; + private char quoteChar = '\''; /** * Creates a new NewickFile object. @@ -257,6 +329,7 @@ public class NewickFile extends FileParse */ public void parse() throws IOException { + Platform.ensureRegex(); String nf; { // fill nf with complete tree file @@ -294,8 +367,7 @@ public class NewickFile extends FileParse boolean ascending = false; // flag indicating that we are leaving the // current node - Regex majorsyms = new Regex( - "[(\\['),;]"); + Regex majorsyms = getRegex(REGEX_MAJOR_SYMS); // "[(\\['),;]" int nextcp = 0; int ncp = cp; @@ -354,8 +426,7 @@ public class NewickFile extends FileParse // Deal with quoted fields case '\'': - Regex qnodename = new Regex( - "'([^']|'')+'"); + Regex qnodename = getRegex(REGEX_QNODE_NAME);// "'([^']|'')+'"); if (qnodename.searchFrom(nf, fcp)) { @@ -363,8 +434,7 @@ public class NewickFile extends FileParse nodename = new String( qnodename.stringMatched().substring(1, nl - 1)); // unpack any escaped colons - Regex xpandquotes = Regex - .perlCode("s/''/'/"); + Regex xpandquotes = getRegex(REGEX_PERL_EXPAND_QUOTES); String widernodename = xpandquotes.replaceAll(nodename); nodename = widernodename; // jump to after end of quoted nodename @@ -398,8 +468,7 @@ public class NewickFile extends FileParse * '"+nf.substring(cp,fcp)+"'"); } */ // verify termination. - Regex comment = new Regex( - "]"); + Regex comment = getRegex(REGEX_COMMENT); // "]" if (comment.searchFrom(nf, fcp)) { // Skip the comment field @@ -430,12 +499,9 @@ public class NewickFile extends FileParse + fstring.substring(cend + 1); } - Regex uqnodename = new Regex( - "\\b([^' :;\\](),]+)"); - Regex nbootstrap = new Regex( - "\\s*([0-9+]+)\\s*:"); - Regex ndist = new Regex( - ":([-0-9Ee.+]+)"); + Regex uqnodename = getRegex(REGEX_UQNODE_NAME);// "\\b([^' :;\\](),]+)" + Regex nbootstrap = getRegex(REGEX_NBOOTSTRAP);// "\\s*([0-9+]+)\\s*:"); + Regex ndist = getRegex(REGEX_NDIST);// ":([-0-9Ee.+]+)"); if (!parsednodename && uqnodename.search(fstring) && ((uqnodename.matchedFrom(1) == 0) || (fstring @@ -790,7 +856,7 @@ public class NewickFile extends FileParse */ char getQuoteChar() { - return QuoteChar; + return quoteChar; } /** @@ -803,8 +869,8 @@ public class NewickFile extends FileParse */ char setQuoteChar(char c) { - char old = QuoteChar; - QuoteChar = c; + char old = quoteChar; + quoteChar = c; return old; } @@ -819,13 +885,15 @@ public class NewickFile extends FileParse */ private String nodeName(String name) { - if (NodeSafeName[0].search(name)) + if (getRegex(REGEX_PERL_NODE_REQUIRE_QUOTE).search(name)) { - return QuoteChar + NodeSafeName[1].replaceAll(name) + QuoteChar; + return quoteChar + + getRegex(REGEX_PERL_NODE_ESCAPE_QUOTE).replaceAll(name) + + quoteChar; } else { - return NodeSafeName[2].replaceAll(name); + return getRegex(REGEX_PERL_NODE_UNQUOTED_WHITESPACE).replaceAll(name); } } @@ -972,7 +1040,7 @@ public class NewickFile extends FileParse trf.parse(); System.out.println("Original file :\n"); - Regex nonl = new Regex("\n+", ""); + Regex nonl = getRegex(REGEX_NO_LINES);// "\n+", ""); System.out.println(nonl.replaceAll(newickfile.toString()) + "\n"); System.out.println("Parsed file.\n"); diff --git a/src/jalview/io/RnamlFile.java b/src/jalview/io/RnamlFile.java index 4d3ddc1..9551992 100644 --- a/src/jalview/io/RnamlFile.java +++ b/src/jalview/io/RnamlFile.java @@ -26,6 +26,7 @@ import jalview.datamodel.Annotation; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceI; import jalview.util.MessageManager; +import jalview.util.Platform; import java.io.BufferedReader; import java.io.FileNotFoundException; @@ -227,7 +228,7 @@ public class RnamlFile extends AlignFile dataName = dataName.substring(0, b - 1); } b = 0; - Regex m = new Regex("[\\/]?([-A-Za-z0-9]+)\\.?"); + Regex m = Platform.newRegex("[\\/]?([-A-Za-z0-9]+)\\.?"); String mm = dataName; while (m.searchFrom(dataName, b)) { diff --git a/src/jalview/io/StockholmFile.java b/src/jalview/io/StockholmFile.java index 8b26757..92f73f4 100644 --- a/src/jalview/io/StockholmFile.java +++ b/src/jalview/io/StockholmFile.java @@ -23,6 +23,21 @@ */ package jalview.io; +import jalview.analysis.Rna; +import jalview.datamodel.AlignmentAnnotation; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.Annotation; +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.Mapping; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.schemes.ResidueProperties; +import jalview.util.Comparison; +import jalview.util.Format; +import jalview.util.MessageManager; +import jalview.util.Platform; + import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; @@ -39,21 +54,6 @@ import com.stevesoft.pat.Regex; import fr.orsay.lri.varna.exceptions.ExceptionUnmatchedClosingParentheses; import fr.orsay.lri.varna.factories.RNAFactory; import fr.orsay.lri.varna.models.rna.RNA; -import jalview.analysis.Rna; -import jalview.datamodel.AlignmentAnnotation; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.Annotation; -import jalview.datamodel.DBRefEntry; -import jalview.datamodel.DBRefSource; -import jalview.datamodel.Mapping; -import jalview.datamodel.Sequence; -import jalview.datamodel.SequenceFeature; -import jalview.datamodel.SequenceI; -import jalview.schemes.ResidueProperties; -import jalview.util.Comparison; -import jalview.util.DBRefUtils; -import jalview.util.Format; -import jalview.util.MessageManager; // import org.apache.log4j.*; @@ -77,20 +77,105 @@ public class StockholmFile extends AlignFile { private static final String ANNOTATION = "annotation"; -// private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "("); -// -// private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")"); - - public static final Regex DETECT_BRACKETS = new Regex( - "(<|>|\\[|\\]|\\(|\\)|\\{|\\})"); + // WUSS extended symbols. Avoid ambiguity with protein SS annotations by using + // NOT_RNASS first. - // WUSS extended symbols. Avoid ambiguity with protein SS annotations by using NOT_RNASS first. public static final String RNASS_BRACKETS = "<>[](){}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; + public static final int REGEX_STOCKHOLM = 0; + + public static final int REGEX_BRACKETS = 1; + // use the following regex to decide an annotations (whole) line is NOT an RNA // SS (it contains only E,H,e,h and other non-brace/non-alpha chars) - private static final Regex NOT_RNASS = new Regex( - "^[^<>[\\](){}A-DF-Za-df-z]*$"); + public static final int REGEX_NOT_RNASS = 2; + + private static final int REGEX_ANNOTATION = 3; + + private static final int REGEX_PFAM = 4; + + private static final int REGEX_RFAM = 5; + + private static final int REGEX_ALIGN_END = 6; + + private static final int REGEX_SPLIT_ID = 7; + + private static final int REGEX_SUBTYPE = 8; + + private static final int REGEX_ANNOTATION_LINE = 9; + + private static final int REGEX_REMOVE_ID = 10; + + private static final int REGEX_OPEN_PAREN = 11; + + private static final int REGEX_CLOSE_PAREN = 12; + + public static final int REGEX_MAX = 13; + + private static Regex REGEX[] = new Regex[REGEX_MAX]; + + /** + * Centralize all actual Regex instantialization in Platform. + * + * @param id + * @return + */ + private static Regex getRegex(int id) + { + if (REGEX[id] == null) + { + String pat = null, pat2 = null; + switch (id) + { + case REGEX_STOCKHOLM: + pat = "# STOCKHOLM ([\\d\\.]+)"; + break; + case REGEX_BRACKETS: + // for reference; not used + pat = "(<|>|\\[|\\]|\\(|\\)|\\{|\\})"; + break; + case REGEX_NOT_RNASS: + pat = "^[^<>[\\](){}A-DF-Za-df-z]*$"; + break; + case REGEX_ANNOTATION: + pat = "(\\w+)\\s*(.*)"; + break; + case REGEX_PFAM: + pat = "PF[0-9]{5}(.*)"; + break; + case REGEX_RFAM: + pat = "RF[0-9]{5}(.*)"; + break; + case REGEX_ALIGN_END: + pat = "^\\s*\\/\\/"; + break; + case REGEX_SPLIT_ID: + pat = "(\\S+)\\/(\\d+)\\-(\\d+)"; + break; + case REGEX_SUBTYPE: + pat = "(\\S+)\\s+(\\S*)\\s+(.*)"; + break; + case REGEX_ANNOTATION_LINE: + pat = "#=(G[FSRC]?)\\s+(.*)"; + break; + case REGEX_REMOVE_ID: + pat = "(\\S+)\\s+(\\S+)"; + break; + case REGEX_OPEN_PAREN: + pat = "(<|\\[)"; + pat2 = "("; + break; + case REGEX_CLOSE_PAREN: + pat = "(>|\\])"; + pat2 = ")"; + break; + default: + return null; + } + REGEX[id] = Platform.newRegex(pat, pat2); + } + return REGEX[id]; + } StringBuffer out; // output buffer @@ -215,7 +300,7 @@ public class StockholmFile extends AlignFile // First, we have to check that this file has STOCKHOLM format, i.e. the // first line must match - r = new Regex("# STOCKHOLM ([\\d\\.]+)"); + r = getRegex(REGEX_STOCKHOLM); if (!r.search(nextLine())) { throw new IOException(MessageManager @@ -229,19 +314,22 @@ public class StockholmFile extends AlignFile } // We define some Regexes here that will be used regularily later - rend = new Regex("^\\s*\\/\\/"); // Find the end of an alignment - p = new Regex("(\\S+)\\/(\\d+)\\-(\\d+)"); // split sequence id in + rend = getRegex(REGEX_ALIGN_END);//"^\\s*\\/\\/"); // Find the end of an alignment + p = getRegex(REGEX_SPLIT_ID);//"(\\S+)\\/(\\d+)\\-(\\d+)"); // split sequence id in // id/from/to - s = new Regex("(\\S+)\\s+(\\S*)\\s+(.*)"); // Parses annotation subtype - r = new Regex("#=(G[FSRC]?)\\s+(.*)"); // Finds any annotation line - x = new Regex("(\\S+)\\s+(\\S+)"); // split id from sequence + s = getRegex(REGEX_SUBTYPE);// "(\\S+)\\s+(\\S*)\\s+(.*)"); // Parses + // annotation subtype + r = getRegex(REGEX_ANNOTATION_LINE);// "#=(G[FSRC]?)\\s+(.*)"); // Finds any + // annotation line + x = getRegex(REGEX_REMOVE_ID);// "(\\S+)\\s+(\\S+)"); // split id from + // sequence // Convert all bracket types to parentheses (necessary for passing to VARNA) - Regex openparen = new Regex("(<|\\[)", "("); - Regex closeparen = new Regex("(>|\\])", ")"); + Regex openparen = getRegex(REGEX_OPEN_PAREN);//"(<|\\[)", "("); + Regex closeparen = getRegex(REGEX_CLOSE_PAREN);//"(>|\\])", ")"); // // Detect if file is RNA by looking for bracket types -// Regex detectbrackets = new Regex("(<|>|\\[|\\]|\\(|\\))"); + // Regex detectbrackets = getRegex("(<|>|\\[|\\]|\\(|\\))"); rend.optimize(); p.optimize(); @@ -263,8 +351,8 @@ public class StockholmFile extends AlignFile this.noSeqs = seqs.size(); String dbsource = null; - Regex pf = new Regex("PF[0-9]{5}(.*)"); // Finds AC for Pfam - Regex rf = new Regex("RF[0-9]{5}(.*)"); // Finds AC for Rfam + Regex pf = getRegex(REGEX_PFAM); // Finds AC for Pfam + Regex rf = getRegex(REGEX_RFAM); // Finds AC for Rfam if (getAlignmentProperty("AC") != null) { String dbType = getAlignmentProperty("AC").toString(); @@ -333,14 +421,17 @@ public class StockholmFile extends AlignFile if (accAnnotations != null && accAnnotations.containsKey("AC")) { - String dbr = (String) accAnnotations.get("AC"); - if (dbr != null) + if (dbsource != null) { - // we could get very clever here - but for now - just try to - // guess accession type from type of sequence, source of alignment plus - // structure - // of accession - guessDatabaseFor(seqO, dbr, dbsource); + String dbr = (String) accAnnotations.get("AC"); + if (dbr != null) + { + // we could get very clever here - but for now - just try to + // guess accession type from source of alignment plus structure + // of accession + guessDatabaseFor(seqO, dbr, dbsource); + + } } // else - do what ? add the data anyway and prompt the user to // specify what references these are ? @@ -505,7 +596,7 @@ public class StockholmFile extends AlignFile */ // Let's save the annotations, maybe we'll be able to do something // with them later... - Regex an = new Regex("(\\w+)\\s*(.*)"); + Regex an = getRegex(REGEX_ANNOTATION); if (an.search(annContent)) { if (an.stringMatched(1).equals("NH")) @@ -525,9 +616,6 @@ public class StockholmFile extends AlignFile treeName = an.stringMatched(2); treeString = new StringBuffer(); } - // TODO: JAL-3532 - this is where GF comments and database references are lost - // suggest overriding this method for Stockholm files to catch and properly - // process CC, DR etc into multivalued properties setAlignmentProperty(an.stringMatched(1), an.stringMatched(2)); } } @@ -756,12 +844,6 @@ public class StockholmFile extends AlignFile st = -1; } } - if (dbsource == null) - { - // make up an origin based on whether the sequence looks like it is nucleotide - // or protein - dbsource = (seqO.isProtein()) ? "PFAM" : "RFAM"; - } if (dbsource.equals("PFAM")) { seqdb = "UNIPROT"; @@ -844,7 +926,8 @@ public class StockholmFile extends AlignFile if (type.equalsIgnoreCase("secondary structure")) { ss = true; - isrnass = !NOT_RNASS.search(annots); // sorry about the double negative + isrnass = !getRegex(REGEX_NOT_RNASS).search(annots); // sorry about the double + // negative // here (it's easier for dealing with // other non-alpha-non-brace chars) } @@ -937,11 +1020,6 @@ public class StockholmFile extends AlignFile return annot; } - private String dbref_to_ac_record(DBRefEntry ref) - { - return ref.getSource().toString() + " ; " - + ref.getAccessionId().toString(); - } @Override public String print(SequenceI[] s, boolean jvSuffix) { @@ -956,7 +1034,6 @@ public class StockholmFile extends AlignFile int slen = s.length; SequenceI seq; Hashtable dataRef = null; - boolean isAA = s[in].isProtein(); while ((in < slen) && ((seq = s[in]) != null)) { String tmp = printId(seq, jvSuffix); @@ -974,29 +1051,14 @@ public class StockholmFile extends AlignFile { dataRef = new Hashtable<>(); } - List primrefs = seq.getPrimaryDBRefs(); - if (primrefs.size() >= 1) + for (int idb = 0; idb < ndb; idb++) { - dataRef.put(tmp, dbref_to_ac_record(primrefs.get(0))); - } - else - { - for (int idb = 0; idb < seq.getDBRefs().size(); idb++) - { - DBRefEntry dbref = seq.getDBRefs().get(idb); - dataRef.put(tmp, dbref_to_ac_record(dbref)); - // if we put in a uniprot or EMBL record then we're done: - if (isAA && DBRefSource.UNIPROT - .equals(DBRefUtils.getCanonicalName(dbref.getSource()))) - { - break; - } - if (!isAA && DBRefSource.EMBL - .equals(DBRefUtils.getCanonicalName(dbref.getSource()))) - { - break; - } - } + + DBRefEntry ref = seqrefs.get(idb); + String datAs1 = ref.getSource().toString() + + " ; " + + ref.getAccessionId().toString(); + dataRef.put(tmp, datAs1); } } in++; @@ -1029,8 +1091,7 @@ public class StockholmFile extends AlignFile String type = dataRef.remove(idd); out.append(new Format("%-" + (maxid - 2) + "s") .form("#=GS " + idd.toString() + " ")); - if (isAA && type.contains("UNIPROT") - || (!isAA && type.contains("EMBL"))) + if (type.contains("PFAM") || type.contains("RFAM")) { out.append(" AC " + type.substring(type.indexOf(";") + 1)); diff --git a/src/jalview/util/DBRefUtils.java b/src/jalview/util/DBRefUtils.java index ae0243e..07e8a56 100755 --- a/src/jalview/util/DBRefUtils.java +++ b/src/jalview/util/DBRefUtils.java @@ -307,6 +307,15 @@ public class DBRefUtils }; + private static Regex PARSE_REGEX; + + private static Regex getParseRegex() + { + return (PARSE_REGEX == null ? PARSE_REGEX = Platform.newRegex( + "([0-9][0-9A-Za-z]{3})\\s*(.?)\\s*;\\s*([0-9]+)-([0-9]+)") + : PARSE_REGEX); + } + /** * Parses a DBRefEntry and adds it to the sequence, also a PDBEntry if the * database is PDB. @@ -334,8 +343,7 @@ public class DBRefUtils * Check for PFAM style stockhom PDB accession id citation e.g. * "1WRI A; 7-80;" */ - Regex r = new com.stevesoft.pat.Regex( - "([0-9][0-9A-Za-z]{3})\\s*(.?)\\s*;\\s*([0-9]+)-([0-9]+)"); + Regex r = getParseRegex(); if (r.search(acn.trim())) { String pdbid = r.stringMatched(1); diff --git a/src/jalview/util/Platform.java b/src/jalview/util/Platform.java index fea40c3..2fa807a 100644 --- a/src/jalview/util/Platform.java +++ b/src/jalview/util/Platform.java @@ -692,6 +692,11 @@ public class Platform } + public static Regex newRegex(String regex) + { + return newRegex(regex, null); + } + public static Regex newRegex(String searchString, String replaceString) { ensureRegex(); @@ -818,6 +823,4 @@ public class Platform } - - } diff --git a/src/jalview/ws/dbsources/EmblCdsSource.java b/src/jalview/ws/dbsources/EmblCdsSource.java index a73af61..796f6e9 100644 --- a/src/jalview/ws/dbsources/EmblCdsSource.java +++ b/src/jalview/ws/dbsources/EmblCdsSource.java @@ -22,11 +22,13 @@ package jalview.ws.dbsources; import jalview.datamodel.AlignmentI; import jalview.datamodel.DBRefSource; +import jalview.util.Platform; import com.stevesoft.pat.Regex; public class EmblCdsSource extends EmblXmlSource { + private Regex ACCESSION_REGEX = null; public EmblCdsSource() { @@ -42,9 +44,14 @@ public class EmblCdsSource extends EmblXmlSource @Override public Regex getAccessionValidator() { - return new Regex("^[A-Z]+[0-9]+"); + if (ACCESSION_REGEX == null) + { + ACCESSION_REGEX = Platform.newRegex("^[A-Z]+[0-9]+"); + } + return ACCESSION_REGEX; } + @Override public String getDbSource() { diff --git a/src/jalview/ws/dbsources/EmblSource.java b/src/jalview/ws/dbsources/EmblSource.java index 6bbe2e1..114f6df 100644 --- a/src/jalview/ws/dbsources/EmblSource.java +++ b/src/jalview/ws/dbsources/EmblSource.java @@ -22,6 +22,7 @@ package jalview.ws.dbsources; import jalview.datamodel.AlignmentI; import jalview.datamodel.DBRefSource; +import jalview.util.Platform; import com.stevesoft.pat.Regex; @@ -32,6 +33,8 @@ import com.stevesoft.pat.Regex; public class EmblSource extends EmblXmlSource { + private static Regex ACCESSION_REGEX; + public EmblSource() { super(); @@ -57,7 +60,11 @@ public class EmblSource extends EmblXmlSource @Override public Regex getAccessionValidator() { - return new Regex("^[A-Z]+[0-9]+"); + if (ACCESSION_REGEX == null) + { + ACCESSION_REGEX = Platform.newRegex("^[A-Z]+[0-9]+"); + } + return ACCESSION_REGEX; } /* diff --git a/src/jalview/ws/dbsources/Pdb.java b/src/jalview/ws/dbsources/Pdb.java index a658089..8951a6e 100644 --- a/src/jalview/ws/dbsources/Pdb.java +++ b/src/jalview/ws/dbsources/Pdb.java @@ -36,6 +36,7 @@ import jalview.io.FormatAdapter; import jalview.io.PDBFeatureSettings; import jalview.structure.StructureImportSettings; import jalview.util.MessageManager; +import jalview.util.Platform; import jalview.ws.ebi.EBIFetchClient; import java.io.File; @@ -56,6 +57,8 @@ public class Pdb extends EbiFileRetrievedProxy private static final int PDB_ID_LENGTH = 4; + private static Regex ACCESSION_REGEX; + public Pdb() { super(); @@ -80,7 +83,12 @@ public class Pdb extends EbiFileRetrievedProxy @Override public Regex getAccessionValidator() { - return new Regex("([1-9][0-9A-Za-z]{3}):?([ _A-Za-z0-9]?)"); + if (ACCESSION_REGEX == null) + { + ACCESSION_REGEX = Platform + .newRegex("([1-9][0-9A-Za-z]{3}):?([ _A-Za-z0-9]?)"); + } + return ACCESSION_REGEX; } /* diff --git a/src/jalview/ws/dbsources/Uniprot.java b/src/jalview/ws/dbsources/Uniprot.java index 6f5f033..6fc913b 100644 --- a/src/jalview/ws/dbsources/Uniprot.java +++ b/src/jalview/ws/dbsources/Uniprot.java @@ -29,7 +29,9 @@ import jalview.datamodel.PDBEntry; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.gui.Preferences; import jalview.schemes.ResidueProperties; +import jalview.util.Platform; import jalview.util.StringUtils; import jalview.ws.seqfetcher.DbSourceProxyImpl; import jalview.xml.binding.embl.ROOT; @@ -71,6 +73,8 @@ public class Uniprot extends DbSourceProxyImpl private static final String BAR_DELIMITER = "|"; + private static Regex ACCESSION_REGEX; + /** * Constructor */ @@ -103,7 +107,12 @@ public class Uniprot extends DbSourceProxyImpl @Override public Regex getAccessionValidator() { - return new Regex("([A-Z]+[0-9]+[A-Z0-9]+|[A-Z0-9]+_[A-Z0-9]+)"); + if (ACCESSION_REGEX == null) + { + ACCESSION_REGEX = Platform + .newRegex("([A-Z]+[0-9]+[A-Z0-9]+|[A-Z0-9]+_[A-Z0-9]+)"); + } + return ACCESSION_REGEX; } /*