001package com.hfg.bio.molbio;
002
003
004import java.util.ArrayList;
005import java.util.List;
006import java.util.Set;
007import java.util.regex.Matcher;
008import java.util.regex.Pattern;
009
010import com.hfg.bio.Strand;
011import com.hfg.bio.seq.SeqLocation;
012import com.hfg.bio.seq.pattern.NucleotidePattern;
013import com.hfg.bio.seq.pattern.SeqPatternConfigurationException;
014import com.hfg.util.StringBuilderPlus;
015import com.hfg.util.StringUtil;
016import com.hfg.util.collection.CollectionUtil;
017import com.hfg.util.collection.OrderedSet;
018
019//------------------------------------------------------------------------------
020/**
021 Restriction enzyme is an endonuclease used for cutting DNA/RNA at specific locations.
022 <div>
023 @author J. Alex Taylor, hairyfatguy.com
024 </div>
025 */
026//------------------------------------------------------------------------------
027// com.hfg Library
028//
029// This library is free software; you can redistribute it and/or
030// modify it under the terms of the GNU Lesser General Public
031// License as published by the Free Software Foundation; either
032// version 2.1 of the License, or (at your option) any later version.
033//
034// This library is distributed in the hope that it will be useful,
035// but WITHOUT ANY WARRANTY; without even the implied warranty of
036// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
037// Lesser General Public License for more details.
038//
039// You should have received a copy of the GNU Lesser General Public
040// License along with this library; if not, write to the Free Software
041// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
042//
043// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
044// jataylor@hairyfatguy.com
045//------------------------------------------------------------------------------
046
047
048public class RestrictionEnzyme extends NucleotidePattern<RestrictionSite>
049{
050   // This declaration has to come before the public constants below.
051   private static Set<RestrictionEnzyme> sValues = new OrderedSet<>();
052
053   private static final Pattern s5PrimeNonPalindromicCutSpecPattern = Pattern.compile("^\\((\\-?\\d+)/(\\-?\\d+)\\)");
054   private static final Pattern s3PrimeNonPalindromicCutSpecPattern = Pattern.compile("\\((\\-?\\d+)/(\\-?\\d+)\\)$");
055
056   private String  mRecognitionSequence;
057   private boolean mIsPalindromic;
058   private int[]   mFwdStrandCutSiteIndices;
059   private int[]   mRevStrandCutSiteIndices;
060
061   //##########################################################################
062   // PUBLIC FIELDS
063   //##########################################################################
064
065   // Recognition site syntax:
066   //    - A backslash in binding site indicates the blunt-end cut site
067   //    - An (optional) numbers in parenthesis following the binding site residues indicates the offset of the forward and reverse strand cuts
068   //      Ex: AarI  CACCTGC(4/8)               Ex: AciI  CCGC(-3/-1)
069   //            CACCTGCNNNN^NNNN                     C^CGC
070   //            GTGGACGNNNN NNNN^                    GGC^G  
071   
072   public static final RestrictionEnzyme AarI      = new RestrictionEnzyme().setName("AarI").setRecognitionSequence("CACCTGC(4/8)").lock().register();
073   public static final RestrictionEnzyme AatII     = new RestrictionEnzyme().setName("AatII").setRecognitionSequence("GACGT/C").lock().register();
074   public static final RestrictionEnzyme AcII      = new RestrictionEnzyme().setName("AcII").setRecognitionSequence("AA/CGTT").lock().register();
075   public static final RestrictionEnzyme AccI      = new RestrictionEnzyme().setName("AccI").setRecognitionSequence("GT/MKAC").lock().register();
076   public static final RestrictionEnzyme Acc65I    = new RestrictionEnzyme().setName("Acc65I").setRecognitionSequence("G/GTACC").lock().register();
077   public static final RestrictionEnzyme AciI      = new RestrictionEnzyme().setName("AciI").setRecognitionSequence("CCGC(-3/-1)").lock().register();
078   public static final RestrictionEnzyme AcuI      = new RestrictionEnzyme().setName("AcuI").setRecognitionSequence("CTGAAG(16/14)").lock().register();
079   public static final RestrictionEnzyme AfeI      = new RestrictionEnzyme().setName("AfeI").setRecognitionSequence("AGC/GCT").lock().register();
080   public static final RestrictionEnzyme AflII     = new RestrictionEnzyme().setName("AflII").setRecognitionSequence("C/TTAAG").lock().register();
081   public static final RestrictionEnzyme AflIII    = new RestrictionEnzyme().setName("AflIII").setRecognitionSequence("A/CRYGT").lock().register();
082   public static final RestrictionEnzyme AgeI      = new RestrictionEnzyme().setName("AgeI").setRecognitionSequence("A/CCGGT").lock().register();
083   public static final RestrictionEnzyme AhdI      = new RestrictionEnzyme().setName("AhdI").setRecognitionSequence("GACNNN/NNGTC").lock().register();
084   public static final RestrictionEnzyme AleI      = new RestrictionEnzyme().setName("AleI").setRecognitionSequence("CACNN/NNGTG").lock().register();
085   public static final RestrictionEnzyme AluI      = new RestrictionEnzyme().setName("AluI").setRecognitionSequence("AG/CT").lock().register();
086   public static final RestrictionEnzyme AlwI      = new RestrictionEnzyme().setName("AlwI").setRecognitionSequence("GGATC(4/5)").lock().register();
087   public static final RestrictionEnzyme AlwNI     = new RestrictionEnzyme().setName("AlwNI").setRecognitionSequence("CAGNNN/CTG").lock().register();
088   public static final RestrictionEnzyme ApaI      = new RestrictionEnzyme().setName("ApaI").setRecognitionSequence("GGGCC/C").lock().register();
089   public static final RestrictionEnzyme ApaLI     = new RestrictionEnzyme().setName("ApaLI").setRecognitionSequence("G/TGCAC").lock().register();
090   public static final RestrictionEnzyme ApoI      = new RestrictionEnzyme().setName("ApoI").setRecognitionSequence("R/AATTY").lock().register();
091   public static final RestrictionEnzyme AscI      = new RestrictionEnzyme().setName("AscI").setRecognitionSequence("GG/CGCGCC").lock().register();
092   public static final RestrictionEnzyme AseI      = new RestrictionEnzyme().setName("AseI").setRecognitionSequence("AT/TAAT").lock().register();
093   public static final RestrictionEnzyme AsiSI     = new RestrictionEnzyme().setName("AsiSI").setRecognitionSequence("GCGAT/CGC").lock().register();
094   public static final RestrictionEnzyme AvaI      = new RestrictionEnzyme().setName("AvaI").setRecognitionSequence("C/YCGRG").lock().register();
095   public static final RestrictionEnzyme AvaII     = new RestrictionEnzyme().setName("AvaII").setRecognitionSequence("G/GWCC").lock().register();
096   public static final RestrictionEnzyme AvrII     = new RestrictionEnzyme().setName("AvrII").setRecognitionSequence("C/CTAGG").lock().register();
097   public static final RestrictionEnzyme BaeI      = new RestrictionEnzyme().setName("BaeI").setRecognitionSequence("(10/15)ACNNNNGTAYC(12/7)").lock().register();
098   public static final RestrictionEnzyme BaeGI     = new RestrictionEnzyme().setName("BaeGI").setRecognitionSequence("GKGCM/C").lock().register();
099   public static final RestrictionEnzyme BamHI     = new RestrictionEnzyme().setName("BamHI").setRecognitionSequence("G/GATCC").lock().register();
100   public static final RestrictionEnzyme BanI      = new RestrictionEnzyme().setName("BanI").setRecognitionSequence("G/GYRCC").lock().register();
101   public static final RestrictionEnzyme BanII     = new RestrictionEnzyme().setName("BanII").setRecognitionSequence("GRGCY/C").lock().register();
102   public static final RestrictionEnzyme BbsI      = new RestrictionEnzyme().setName("BbsI").setRecognitionSequence("GAAGAC(2/6)").lock().register();
103   public static final RestrictionEnzyme BbvI      = new RestrictionEnzyme().setName("BbvI").setRecognitionSequence("GCAGC(8/12)").lock().register();
104   public static final RestrictionEnzyme BbvCI     = new RestrictionEnzyme().setName("BbvCI").setRecognitionSequence("CCTCAGC(-5/-2)").lock().register();
105   public static final RestrictionEnzyme BccI      = new RestrictionEnzyme().setName("BccI").setRecognitionSequence("CCATC(4/5)").lock().register();
106   public static final RestrictionEnzyme BceAI     = new RestrictionEnzyme().setName("BceAI").setRecognitionSequence("ACGGC(12/14)").lock().register();
107   public static final RestrictionEnzyme BcgI      = new RestrictionEnzyme().setName("BcgI").setRecognitionSequence("(10/12)CGANNNNNNTGC(12/10)").lock().register();
108   public static final RestrictionEnzyme BciVI     = new RestrictionEnzyme().setName("BciVI").setRecognitionSequence("GTATCC(6/5)").lock().register();
109   public static final RestrictionEnzyme BclI      = new RestrictionEnzyme().setName("BclI").setRecognitionSequence("T/GATCA").lock().register();
110   public static final RestrictionEnzyme BfaI      = new RestrictionEnzyme().setName("BfaI").setRecognitionSequence("C/TAG").lock().register();
111   public static final RestrictionEnzyme BglI      = new RestrictionEnzyme().setName("BglI").setRecognitionSequence("GCCNNNN/NGGC").lock().register();
112   public static final RestrictionEnzyme BglII     = new RestrictionEnzyme().setName("BglII").setRecognitionSequence("A/GATCT").lock().register();
113   public static final RestrictionEnzyme BlpI      = new RestrictionEnzyme().setName("BlpI").setRecognitionSequence("GC/TNAGC").lock().register();
114   public static final RestrictionEnzyme BmgBI     = new RestrictionEnzyme().setName("BmgBI").setRecognitionSequence("CACGTC(-3/-3)").lock().register();
115   public static final RestrictionEnzyme BmrI      = new RestrictionEnzyme().setName("BmrI").setRecognitionSequence("ACTGGG(5/4)").lock().register();
116   public static final RestrictionEnzyme BmtI      = new RestrictionEnzyme().setName("BmtI").setRecognitionSequence("GCTAG/C").lock().register();
117   public static final RestrictionEnzyme BpmI      = new RestrictionEnzyme().setName("BpmI").setRecognitionSequence("CTGGAG(16/14)").lock().register();
118   public static final RestrictionEnzyme BpuEI     = new RestrictionEnzyme().setName("BpuEI").setRecognitionSequence("CTTGAG(16/14)").lock().register();
119   public static final RestrictionEnzyme Bpu10I    = new RestrictionEnzyme().setName("Bpu10I").setRecognitionSequence("CCTNAGC(-5/-2)").lock().register();
120   public static final RestrictionEnzyme BsaI      = new RestrictionEnzyme().setName("BsaI").setRecognitionSequence("GGTCTC(1/5)").lock().register();
121   public static final RestrictionEnzyme BsaAI     = new RestrictionEnzyme().setName("BsaAI").setRecognitionSequence("YAC/GTR").lock().register();
122   public static final RestrictionEnzyme BsaBI     = new RestrictionEnzyme().setName("BsaBI").setRecognitionSequence("GATNN/NNATC").lock().register();
123   public static final RestrictionEnzyme BsaHI     = new RestrictionEnzyme().setName("BsaHI").setRecognitionSequence("GR/CGYC").lock().register();
124   public static final RestrictionEnzyme BsaJI     = new RestrictionEnzyme().setName("BsaJI").setRecognitionSequence("C/CNNGG").lock().register();
125   public static final RestrictionEnzyme BsaXI     = new RestrictionEnzyme().setName("BsaXI").setRecognitionSequence("(9/12)ACNNNNNCTCC(10/7)").lock().register();
126   public static final RestrictionEnzyme BseRI     = new RestrictionEnzyme().setName("BseRI").setRecognitionSequence("GAGGAG(10/8)").lock().register();
127   public static final RestrictionEnzyme BsaWI     = new RestrictionEnzyme().setName("BsaWI").setRecognitionSequence("W/CCGGW").lock().register();
128   public static final RestrictionEnzyme BseYI     = new RestrictionEnzyme().setName("BseYI").setRecognitionSequence("CCCAGC(-5/-1)").lock().register();
129   public static final RestrictionEnzyme BsgI      = new RestrictionEnzyme().setName("BsgI").setRecognitionSequence("GTGCAG(16/14)").lock().register();
130   public static final RestrictionEnzyme BsiEI     = new RestrictionEnzyme().setName("BsiEI").setRecognitionSequence("CGRY/CG").lock().register();
131   public static final RestrictionEnzyme BsiHKAI   = new RestrictionEnzyme().setName("BsiHKAI").setRecognitionSequence("GWGCW/C").lock().register();
132   public static final RestrictionEnzyme BsiWI     = new RestrictionEnzyme().setName("BsiWI").setRecognitionSequence("C/GTACG").lock().register();
133   public static final RestrictionEnzyme BslI      = new RestrictionEnzyme().setName("BslI").setRecognitionSequence("CCNNNNN/NNGG").lock().register();
134   public static final RestrictionEnzyme BsmI      = new RestrictionEnzyme().setName("BsmI").setRecognitionSequence("GAATGC(1/-1)").lock().register();
135   public static final RestrictionEnzyme BsmAI     = new RestrictionEnzyme().setName("BsmAI").setRecognitionSequence("GTCTC(1/5)").lock().register();
136   public static final RestrictionEnzyme BsmBI     = new RestrictionEnzyme().setName("BsmBI").setRecognitionSequence("CGTCTC(1/5)").lock().register();
137   public static final RestrictionEnzyme BsmFI     = new RestrictionEnzyme().setName("BsmFI").setRecognitionSequence("GGGAC(10/14)").lock().register();
138   public static final RestrictionEnzyme Bsp1286I  = new RestrictionEnzyme().setName("Bsp1286I").setRecognitionSequence("GDGCH/C").lock().register();
139   public static final RestrictionEnzyme BspCNI    = new RestrictionEnzyme().setName("BspCNI").setRecognitionSequence("CTCAG(9/7)").lock().register();
140   public static final RestrictionEnzyme BspEI     = new RestrictionEnzyme().setName("BspEI").setRecognitionSequence("T/CCGGA").lock().register();
141   public static final RestrictionEnzyme BspHI     = new RestrictionEnzyme().setName("BspHI").setRecognitionSequence("T/CATGA").lock().register();
142   public static final RestrictionEnzyme BspMI     = new RestrictionEnzyme().setName("BspMI").setRecognitionSequence("ACCTGC(4/8)").lock().register();
143   public static final RestrictionEnzyme BsrI      = new RestrictionEnzyme().setName("BsrI").setRecognitionSequence("ACTGG(1/-1)").lock().register();
144   public static final RestrictionEnzyme BsrBI     = new RestrictionEnzyme().setName("BsrBI").setRecognitionSequence("CCGCTC(-3/-3)").lock().register();
145   public static final RestrictionEnzyme BsrDI     = new RestrictionEnzyme().setName("BsrDI").setRecognitionSequence("GCAATG(2/0)").lock().register();
146   public static final RestrictionEnzyme BsrFI     = new RestrictionEnzyme().setName("BsrFI").setRecognitionSequence("R/CCGGY").lock().register();
147   public static final RestrictionEnzyme BsrGI     = new RestrictionEnzyme().setName("BsrGI").setRecognitionSequence("T/GTACA").lock().register();
148   public static final RestrictionEnzyme BssHII    = new RestrictionEnzyme().setName("BssHII").setRecognitionSequence("G/CGCGC").lock().register();
149   public static final RestrictionEnzyme BssKI     = new RestrictionEnzyme().setName("BssKI").setRecognitionSequence("/CCNGG").lock().register();
150   public static final RestrictionEnzyme BssSI     = new RestrictionEnzyme().setName("BssSI").setRecognitionSequence("CACGAG(-5/-1)").lock().register();
151   public static final RestrictionEnzyme BstAPI    = new RestrictionEnzyme().setName("BstAPI").setRecognitionSequence("GCANNNN/NTGC").lock().register();
152   public static final RestrictionEnzyme BstBI     = new RestrictionEnzyme().setName("BstBI").setRecognitionSequence("TT/CGAA").lock().register();
153   public static final RestrictionEnzyme BstEII    = new RestrictionEnzyme().setName("BstEII").setRecognitionSequence("G/GTNACC").lock().register();
154   public static final RestrictionEnzyme BstNI     = new RestrictionEnzyme().setName("BstNI").setRecognitionSequence("CC/WGG").lock().register();
155   public static final RestrictionEnzyme BstUI     = new RestrictionEnzyme().setName("BstUI").setRecognitionSequence("CG/CG").lock().register();
156   public static final RestrictionEnzyme BstXI     = new RestrictionEnzyme().setName("BstXI").setRecognitionSequence("CCANNNNN/NTGG").lock().register();
157   public static final RestrictionEnzyme BstYI     = new RestrictionEnzyme().setName("BstYI").setRecognitionSequence("R/GATCY").lock().register();
158   public static final RestrictionEnzyme BstZ17I   = new RestrictionEnzyme().setName("BstZ17I").setRecognitionSequence("GTA/TAC").lock().register();
159   public static final RestrictionEnzyme Bsu36I    = new RestrictionEnzyme().setName("Bsu36I").setRecognitionSequence("CC/TNAGG").lock().register();
160   public static final RestrictionEnzyme BtgI      = new RestrictionEnzyme().setName("BtgI").setRecognitionSequence("C/CRYGG").lock().register();
161   public static final RestrictionEnzyme BtgZI     = new RestrictionEnzyme().setName("BtgZI").setRecognitionSequence("GCGATG(10/14)").lock().register();
162   public static final RestrictionEnzyme BtsI      = new RestrictionEnzyme().setName("BtsI").setRecognitionSequence("GCAGTG(2/0)").lock().register();
163   public static final RestrictionEnzyme BtsCI     = new RestrictionEnzyme().setName("BtsCI").setRecognitionSequence("GGATG(2/0)").lock().register();
164   public static final RestrictionEnzyme BtsIMutI  = new RestrictionEnzyme().setName("BtsIMutI").setRecognitionSequence("CAGTG(2/0)").lock().register();
165   public static final RestrictionEnzyme Cac8I     = new RestrictionEnzyme().setName("Cac8I").setRecognitionSequence("GCN/NGC").lock().register();
166   public static final RestrictionEnzyme ClaI      = new RestrictionEnzyme().setName("ClaI").setRecognitionSequence("AT/CGAT").lock().register();
167   public static final RestrictionEnzyme CspCI     = new RestrictionEnzyme().setName("CspCI").setRecognitionSequence("(11/13)CAANNNNNGTGG(12/10)").lock().register();
168   public static final RestrictionEnzyme CviAII    = new RestrictionEnzyme().setName("CviAII").setRecognitionSequence("C/ATG").lock().register();
169   public static final RestrictionEnzyme CviKI_1   = new RestrictionEnzyme().setName("CviKI-1").setRecognitionSequence("RG/CY").lock().register();
170   public static final RestrictionEnzyme CviQI     = new RestrictionEnzyme().setName("CviQI").setRecognitionSequence("G/TAC").lock().register();
171   public static final RestrictionEnzyme DdeI      = new RestrictionEnzyme().setName("DdeI").setRecognitionSequence("C/TNAG").lock().register();
172   public static final RestrictionEnzyme DpnI      = new RestrictionEnzyme().setName("DpnI").setRecognitionSequence("GA/TC").lock().register();
173   public static final RestrictionEnzyme DraI      = new RestrictionEnzyme().setName("DraI").setRecognitionSequence("TTT/AAA").lock().register();
174   public static final RestrictionEnzyme DraIII    = new RestrictionEnzyme().setName("DraIII").setRecognitionSequence("CACNNN/GTG").lock().register();
175   public static final RestrictionEnzyme DrdI      = new RestrictionEnzyme().setName("DrdI").setRecognitionSequence("GACNNNN/NNGTC").lock().register();
176   public static final RestrictionEnzyme EaeI      = new RestrictionEnzyme().setName("EaeI").setRecognitionSequence("Y/GGCCR").lock().register();
177   public static final RestrictionEnzyme EagI      = new RestrictionEnzyme().setName("EagI").setRecognitionSequence("C/GGCCG").lock().register();
178   public static final RestrictionEnzyme EarI      = new RestrictionEnzyme().setName("EarI").setRecognitionSequence("CTCTTC(1/4)").lock().register();
179   public static final RestrictionEnzyme EciI      = new RestrictionEnzyme().setName("EciI").setRecognitionSequence("GGCGGA(11/9)").lock().register();
180   public static final RestrictionEnzyme Eco53kI   = new RestrictionEnzyme().setName("Eco53kI").setRecognitionSequence("GAG/CTC").lock().register();
181   public static final RestrictionEnzyme EcoO109I  = new RestrictionEnzyme().setName("EcoO109I").setRecognitionSequence("RG/GNCCY").lock().register();
182   public static final RestrictionEnzyme EcoNI     = new RestrictionEnzyme().setName("EcoNI").setRecognitionSequence("CCTNN/NNNAGG").lock().register();
183   public static final RestrictionEnzyme EcoP15I   = new RestrictionEnzyme().setName("EcoP15I").setRecognitionSequence("CAGCAG(25/27)").lock().register();
184   public static final RestrictionEnzyme EcoRI     = new RestrictionEnzyme().setName("EcoRI").setRecognitionSequence("G/AATTC").lock().register();
185   public static final RestrictionEnzyme EcoRV     = new RestrictionEnzyme().setName("EcoRV").setRecognitionSequence("GAT/ATC").lock().register();
186   public static final RestrictionEnzyme FatI      = new RestrictionEnzyme().setName("FatI").setRecognitionSequence("/CATG").lock().register();
187   public static final RestrictionEnzyme FauI      = new RestrictionEnzyme().setName("FauI").setRecognitionSequence("CCCGC(4/6)").lock().register();
188   public static final RestrictionEnzyme Fnu4HI    = new RestrictionEnzyme().setName("Fnu4HI").setRecognitionSequence("GC/NGC").lock().register();
189   public static final RestrictionEnzyme FokI      = new RestrictionEnzyme().setName("FokI").setRecognitionSequence("GGATG(9/13)").lock().register();
190   public static final RestrictionEnzyme FseI      = new RestrictionEnzyme().setName("FseI").setRecognitionSequence("GGCCGG/CC").lock().register();
191   public static final RestrictionEnzyme FspI      = new RestrictionEnzyme().setName("FspI").setRecognitionSequence("TGC/GCA").lock().register();
192   public static final RestrictionEnzyme FspEI     = new RestrictionEnzyme().setName("FspEI").setRecognitionSequence("CC(12/16)").lock().register();
193   public static final RestrictionEnzyme HaeII     = new RestrictionEnzyme().setName("HaeII").setRecognitionSequence("RGCGC/Y").lock().register();
194   public static final RestrictionEnzyme HaeIII    = new RestrictionEnzyme().setName("HaeIII").setRecognitionSequence("GG/CC").lock().register();
195   public static final RestrictionEnzyme HgaI      = new RestrictionEnzyme().setName("HgaI").setRecognitionSequence("GACGC(5/10)").lock().register();
196   public static final RestrictionEnzyme HhaI      = new RestrictionEnzyme().setName("HhaI").setRecognitionSequence("GCG/C").lock().register();
197   public static final RestrictionEnzyme HincII    = new RestrictionEnzyme().setName("HincII").setRecognitionSequence("GTY/RAC").lock().register();
198   public static final RestrictionEnzyme HindIII   = new RestrictionEnzyme().setName("HindIII").setRecognitionSequence("A/AGCTT").lock().register();
199   public static final RestrictionEnzyme HinfI     = new RestrictionEnzyme().setName("HinfI").setRecognitionSequence("G/ANTC").lock().register();
200   public static final RestrictionEnzyme HinP1I    = new RestrictionEnzyme().setName("HinP1I").setRecognitionSequence("G/CGC").lock().register();
201   public static final RestrictionEnzyme HpaI      = new RestrictionEnzyme().setName("HpaI").setRecognitionSequence("GTT/AAC").lock().register();
202   public static final RestrictionEnzyme HphI      = new RestrictionEnzyme().setName("HphI").setRecognitionSequence("GGTGA(8/7)").lock().register();
203   public static final RestrictionEnzyme Hpy99I    = new RestrictionEnzyme().setName("Hpy99I").setRecognitionSequence("CGWCG/").lock().register();
204   public static final RestrictionEnzyme Hpy166II  = new RestrictionEnzyme().setName("Hpy166II").setRecognitionSequence("GTN/NAC").lock().register();
205   public static final RestrictionEnzyme Hpy188I   = new RestrictionEnzyme().setName("Hpy188I").setRecognitionSequence("TCN/GA").lock().register();
206   public static final RestrictionEnzyme Hpy188III = new RestrictionEnzyme().setName("Hpy188III").setRecognitionSequence("TC/NNGA").lock().register();
207   public static final RestrictionEnzyme HpyAV     = new RestrictionEnzyme().setName("HpyAV").setRecognitionSequence("CCTTC(6/5)").lock().register();
208   public static final RestrictionEnzyme HpyCH4III = new RestrictionEnzyme().setName("HpyCH4III").setRecognitionSequence("ACN/GT").lock().register();
209   public static final RestrictionEnzyme HpyCH4IV  = new RestrictionEnzyme().setName("HpyCH4IV").setRecognitionSequence("A/CGT").lock().register();
210   public static final RestrictionEnzyme HpyCH4V   = new RestrictionEnzyme().setName("HpyCH4V").setRecognitionSequence("TG/CA").lock().register();
211   public static final RestrictionEnzyme I_CeuI    = new RestrictionEnzyme().setName("I-CeuI").setRecognitionSequence("TAACTATAACGGTCCTAAGGTAGCGAA(-9/-13)").lock().register();
212   public static final RestrictionEnzyme I_SceI    = new RestrictionEnzyme().setName("I-SceI").setRecognitionSequence("TAGGGATAACAGGGTAAT(-9/-13)").lock().register();
213   public static final RestrictionEnzyme KasI      = new RestrictionEnzyme().setName("KasI").setRecognitionSequence("G/GCGCC").lock().register();
214   public static final RestrictionEnzyme KpnI      = new RestrictionEnzyme().setName("KpnI").setRecognitionSequence("GGTAC/C").lock().register();
215   public static final RestrictionEnzyme LpnPI     = new RestrictionEnzyme().setName("LpnPI").setRecognitionSequence("CCDG(10/14)").lock().register();
216   public static final RestrictionEnzyme MboI      = new RestrictionEnzyme().setName("MboI").setRecognitionSequence("/GATC").lock().register();
217   public static final RestrictionEnzyme MboII     = new RestrictionEnzyme().setName("MboII").setRecognitionSequence("GAAGA(8/7)").lock().register();
218   public static final RestrictionEnzyme MfeI      = new RestrictionEnzyme().setName("MfeI").setRecognitionSequence("C/AATTG").lock().register();
219   public static final RestrictionEnzyme MluI      = new RestrictionEnzyme().setName("MluI").setRecognitionSequence("A/CGCGT").lock().register();
220   public static final RestrictionEnzyme MluCI     = new RestrictionEnzyme().setName("MluCI").setRecognitionSequence("/AATT").lock().register();
221   public static final RestrictionEnzyme MlyI      = new RestrictionEnzyme().setName("MlyI").setRecognitionSequence("GAGTC(5/5)").lock().register();
222   public static final RestrictionEnzyme MmeI      = new RestrictionEnzyme().setName("MmeI").setRecognitionSequence("TCCRAC(20/18)").lock().register();
223   public static final RestrictionEnzyme MnlI      = new RestrictionEnzyme().setName("MnlI").setRecognitionSequence("CCTC(7/6)").lock().register();
224   public static final RestrictionEnzyme MscI      = new RestrictionEnzyme().setName("MscI").setRecognitionSequence("TGG/CCA").lock().register();
225   public static final RestrictionEnzyme MseI      = new RestrictionEnzyme().setName("MseI").setRecognitionSequence("T/TAA").lock().register();
226   public static final RestrictionEnzyme MslI      = new RestrictionEnzyme().setName("MslI").setRecognitionSequence("CAYNN/NNRTG").lock().register();
227   public static final RestrictionEnzyme MspI      = new RestrictionEnzyme().setName("MspI").setRecognitionSequence("C/CGG").lock().register();
228   public static final RestrictionEnzyme MspA1I    = new RestrictionEnzyme().setName("MspA1I").setRecognitionSequence("CMG/CKG").lock().register();
229   public static final RestrictionEnzyme MspJI     = new RestrictionEnzyme().setName("MspJI").setRecognitionSequence("CNNR(9/13)").lock().register();
230   public static final RestrictionEnzyme MwoI      = new RestrictionEnzyme().setName("MwoI").setRecognitionSequence("GCNNNNN/NNGC").lock().register();
231   public static final RestrictionEnzyme NaeI      = new RestrictionEnzyme().setName("NaeI").setRecognitionSequence("GCC/GGC").lock().register();
232   public static final RestrictionEnzyme NarI      = new RestrictionEnzyme().setName("NarI").setRecognitionSequence("GG/CGCC").lock().register();
233   public static final RestrictionEnzyme NciI      = new RestrictionEnzyme().setName("NciI").setRecognitionSequence("CC/SGG").lock().register();
234   public static final RestrictionEnzyme NcoI      = new RestrictionEnzyme().setName("NcoI").setRecognitionSequence("C/CATGG").lock().register();
235   public static final RestrictionEnzyme NdeI      = new RestrictionEnzyme().setName("NdeI").setRecognitionSequence("CA/TATG").lock().register();
236   public static final RestrictionEnzyme NgoMIV    = new RestrictionEnzyme().setName("NgoMIV").setRecognitionSequence("G/CCGGC").lock().register();
237   public static final RestrictionEnzyme NheI      = new RestrictionEnzyme().setName("NheI").setRecognitionSequence("G/CTAGC").lock().register();
238   public static final RestrictionEnzyme NlaIII    = new RestrictionEnzyme().setName("NlaIII").setRecognitionSequence("CATG/").lock().register();
239   public static final RestrictionEnzyme NlaIV     = new RestrictionEnzyme().setName("NlaIV").setRecognitionSequence("GGN/NCC").lock().register();
240   public static final RestrictionEnzyme NmeAIII   = new RestrictionEnzyme().setName("NmeAIII").setRecognitionSequence("GCCGAG(21/19)").lock().register();
241   public static final RestrictionEnzyme NotI      = new RestrictionEnzyme().setName("NotI").setRecognitionSequence("GC/GGCCGC").lock().register();
242   public static final RestrictionEnzyme NruI      = new RestrictionEnzyme().setName("NruI").setRecognitionSequence("TCG/CGA").lock().register();
243   public static final RestrictionEnzyme NsiI      = new RestrictionEnzyme().setName("NsiI").setRecognitionSequence("ATGCA/T").lock().register();
244   public static final RestrictionEnzyme NspI      = new RestrictionEnzyme().setName("NspI").setRecognitionSequence("RCATG/Y").lock().register();
245   public static final RestrictionEnzyme Nt_AlwI   = new RestrictionEnzyme().setName("Nt.AlwI").setRecognitionSequence("GGATC(4/-5)").lock().register();
246   public static final RestrictionEnzyme Nt_BbvCI  = new RestrictionEnzyme().setName("Nt.BbvCI").setRecognitionSequence("CCTCAGC(-5/-7)").lock().register();
247   public static final RestrictionEnzyme Nt_BsmAI  = new RestrictionEnzyme().setName("Nt.BsmAI").setRecognitionSequence("GTCTC(1/-5)").lock().register();
248   public static final RestrictionEnzyme Nt_BspQI  = new RestrictionEnzyme().setName("Nt.BspQI").setRecognitionSequence("GCTCTTC(1/-7)").lock().register();
249   public static final RestrictionEnzyme Nt_BstNBI = new RestrictionEnzyme().setName("Nt.BstNBI").setRecognitionSequence("GAGTC(4/-5)").lock().register();
250   public static final RestrictionEnzyme Nt_CviPII = new RestrictionEnzyme().setName("Nt.CviPII").setRecognitionSequence("(0/-1)CCD").lock().register();
251   public static final RestrictionEnzyme PacI      = new RestrictionEnzyme().setName("PacI").setRecognitionSequence("TTAAT/TAA").lock().register();
252   public static final RestrictionEnzyme PciI      = new RestrictionEnzyme().setName("PciI").setRecognitionSequence("A/CATGT").lock().register();
253   public static final RestrictionEnzyme PflMI     = new RestrictionEnzyme().setName("PflMI").setRecognitionSequence("CCANNNN/NTGG").lock().register();
254   public static final RestrictionEnzyme PI_PspI   = new RestrictionEnzyme().setName("PI-PspI").setRecognitionSequence("TGGCAAACAGCTATTATGGGTATTATGGGT(-13/-17)").lock().register();
255   public static final RestrictionEnzyme PI_SceI   = new RestrictionEnzyme().setName("PI-SceI").setRecognitionSequence("ATCTATGTCGGGTGCGGAGAAAGAGGTAAT(-15/-19)").lock().register();
256   public static final RestrictionEnzyme PleI      = new RestrictionEnzyme().setName("PleI").setRecognitionSequence("GAGTC(4/5)").lock().register();
257   public static final RestrictionEnzyme PluTI     = new RestrictionEnzyme().setName("PluTI").setRecognitionSequence("GGCGC/C").lock().register();
258   public static final RestrictionEnzyme PmeI      = new RestrictionEnzyme().setName("PmeI").setRecognitionSequence("GTTT/AAAC").lock().register();
259   public static final RestrictionEnzyme PmlI      = new RestrictionEnzyme().setName("PmlI").setRecognitionSequence("CAC/GTG").lock().register();
260   public static final RestrictionEnzyme PpuMI     = new RestrictionEnzyme().setName("PpuMI").setRecognitionSequence("RG/GWCCY").lock().register();
261   public static final RestrictionEnzyme PshAI     = new RestrictionEnzyme().setName("PshAI").setRecognitionSequence("GACNN/NNGTC").lock().register();
262   public static final RestrictionEnzyme PsiI      = new RestrictionEnzyme().setName("PsiI").setRecognitionSequence("TTA/TAA").lock().register();
263   public static final RestrictionEnzyme PspGI     = new RestrictionEnzyme().setName("PspGI").setRecognitionSequence("/CCWGG").lock().register();
264   public static final RestrictionEnzyme PspOMI    = new RestrictionEnzyme().setName("PspOMI").setRecognitionSequence("G/GGCCC").lock().register();
265   public static final RestrictionEnzyme PspXI     = new RestrictionEnzyme().setName("PspXI").setRecognitionSequence("VC/TCGAGB").lock().register();
266   public static final RestrictionEnzyme PstI      = new RestrictionEnzyme().setName("PstI").setRecognitionSequence("CTGCA/G").lock().register();
267   public static final RestrictionEnzyme PvuI      = new RestrictionEnzyme().setName("PvuI").setRecognitionSequence("CGAT/CG").lock().register();
268   public static final RestrictionEnzyme PvuII     = new RestrictionEnzyme().setName("PvuII").setRecognitionSequence("CAG/CTG").lock().register();
269   public static final RestrictionEnzyme RsaI      = new RestrictionEnzyme().setName("RsaI").setRecognitionSequence("GT/AC").lock().register();
270   public static final RestrictionEnzyme RsrII     = new RestrictionEnzyme().setName("RsrII").setRecognitionSequence("CG/GWCCG").lock().register();
271   public static final RestrictionEnzyme SacI      = new RestrictionEnzyme().setName("SacI").setRecognitionSequence("GAGCT/C").lock().register();
272   public static final RestrictionEnzyme SacII     = new RestrictionEnzyme().setName("SacII").setRecognitionSequence("CCGC/GG").lock().register();
273   public static final RestrictionEnzyme SalI      = new RestrictionEnzyme().setName("SalI").setRecognitionSequence("G/TCGAC").lock().register();
274   public static final RestrictionEnzyme SapI      = new RestrictionEnzyme().setName("SapI").setRecognitionSequence("GCTCTTC(1/4)").lock().register();
275   public static final RestrictionEnzyme Sau96I    = new RestrictionEnzyme().setName("Sau96I").setRecognitionSequence("G/GNCC").lock().register();
276   public static final RestrictionEnzyme SbfI      = new RestrictionEnzyme().setName("SbfI").setRecognitionSequence("CCTGCA/GG").lock().register();
277   public static final RestrictionEnzyme ScaI      = new RestrictionEnzyme().setName("ScaI").setRecognitionSequence("AGT/ACT").lock().register();
278   public static final RestrictionEnzyme ScrFI     = new RestrictionEnzyme().setName("ScrFI").setRecognitionSequence("CC/NGG").lock().register();
279   public static final RestrictionEnzyme SexAI     = new RestrictionEnzyme().setName("SexAI").setRecognitionSequence("A/CCWGGT").lock().register();
280   public static final RestrictionEnzyme SfaNI     = new RestrictionEnzyme().setName("SfaNI").setRecognitionSequence("GCATC(5/9)").lock().register();
281   public static final RestrictionEnzyme SfcI      = new RestrictionEnzyme().setName("SfcI").setRecognitionSequence("C/TRYAG").lock().register();
282   public static final RestrictionEnzyme SfiI      = new RestrictionEnzyme().setName("SfiI").setRecognitionSequence("GGCCNNNN/NGGCC").lock().register();
283   public static final RestrictionEnzyme SfoI      = new RestrictionEnzyme().setName("SfoI").setRecognitionSequence("GGC/GCC").lock().register();
284   public static final RestrictionEnzyme SgrAI     = new RestrictionEnzyme().setName("SgrAI").setRecognitionSequence("CR/CCGGYG").lock().register();
285   public static final RestrictionEnzyme SmaI      = new RestrictionEnzyme().setName("SmaI").setRecognitionSequence("CCC/GGG").lock().register();
286   public static final RestrictionEnzyme SmlI      = new RestrictionEnzyme().setName("SmlI").setRecognitionSequence("C/TYRAG").lock().register();
287   public static final RestrictionEnzyme SnaBI     = new RestrictionEnzyme().setName("SnaBI").setRecognitionSequence("TAC/GTA").lock().register();
288   public static final RestrictionEnzyme SpeI      = new RestrictionEnzyme().setName("SpeI").setRecognitionSequence("A/CTAGT").lock().register();
289   public static final RestrictionEnzyme SphI      = new RestrictionEnzyme().setName("SphI").setRecognitionSequence("GCATG/C").lock().register();
290   public static final RestrictionEnzyme SrfI      = new RestrictionEnzyme().setName("SrfI").setRecognitionSequence("GCCC/GGGC").lock().register();
291   public static final RestrictionEnzyme SspI      = new RestrictionEnzyme().setName("SspI").setRecognitionSequence("AAT/ATT").lock().register();
292   public static final RestrictionEnzyme StuI      = new RestrictionEnzyme().setName("StuI").setRecognitionSequence("AGG/CCT").lock().register();
293   public static final RestrictionEnzyme StyI      = new RestrictionEnzyme().setName("StyI").setRecognitionSequence("C/CWWGG").lock().register();
294   public static final RestrictionEnzyme SwaI      = new RestrictionEnzyme().setName("SwaI").setRecognitionSequence("ATTT/AAAT").lock().register();
295   public static final RestrictionEnzyme TaqAI     = new RestrictionEnzyme().setName("TaqAI").setRecognitionSequence("T/CGA").lock().register();
296   public static final RestrictionEnzyme TfiI      = new RestrictionEnzyme().setName("TfiI").setRecognitionSequence("G/AWTC").lock().register();
297   public static final RestrictionEnzyme TseI      = new RestrictionEnzyme().setName("TseI").setRecognitionSequence("G/CWGC").lock().register();
298   public static final RestrictionEnzyme Tsp45I    = new RestrictionEnzyme().setName("Tsp45I").setRecognitionSequence("/GTSAC").lock().register();
299   public static final RestrictionEnzyme TspRI     = new RestrictionEnzyme().setName("TspRI").setRecognitionSequence("NNCASTGNN/").lock().register();
300   public static final RestrictionEnzyme Tth111I   = new RestrictionEnzyme().setName("Tth111I").setRecognitionSequence("GACN/NNGTC").lock().register();
301   public static final RestrictionEnzyme XbaI      = new RestrictionEnzyme().setName("XbaI").setRecognitionSequence("T/CTAGA").lock().register();
302   public static final RestrictionEnzyme XcmI      = new RestrictionEnzyme().setName("XcmI").setRecognitionSequence("CCANNNNN/NNNNTGG").lock().register();
303   public static final RestrictionEnzyme XhoI      = new RestrictionEnzyme().setName("XhoI").setRecognitionSequence("C/TCGAG").lock().register();
304   public static final RestrictionEnzyme XmaI      = new RestrictionEnzyme().setName("XmaI").setRecognitionSequence("C/CCGGG").lock().register();
305   public static final RestrictionEnzyme XmnI      = new RestrictionEnzyme().setName("XmnI").setRecognitionSequence("GAANN/NNTTC").lock().register();
306   public static final RestrictionEnzyme ZraI      = new RestrictionEnzyme().setName("ZraI").setRecognitionSequence("GAC/GTC").lock().register();
307
308
309   //###########################################################################
310   // CONSTRUCTORS
311   //###########################################################################
312
313   //---------------------------------------------------------------------------
314   public RestrictionEnzyme()
315   {
316
317   }
318
319   //###########################################################################
320   // PUBLIC METHODS
321   //###########################################################################
322
323   //---------------------------------------------------------------------------
324   public RestrictionEnzyme setName(String inValue)
325   {
326      return (RestrictionEnzyme) super.setName(inValue);
327   }
328
329   //---------------------------------------------------------------------------
330   @Override
331   public String toString()
332   {
333      return name();
334   }
335
336
337   //---------------------------------------------------------------------------
338   public RestrictionEnzyme setRecognitionSequence(String inValue)
339   {
340      if (! StringUtil.isSet(inValue))
341      {
342         throw new SeqPatternConfigurationException("Empty recognition sequence specified!");
343      }
344
345      mRecognitionSequence = inValue;
346      setPrositePattern(extractPrositePattern());
347
348
349      if (!mIsPalindromic)
350      {
351         setStrandsToSearch(Strand.values());
352      }
353      else
354      {
355         setStrandsToSearch(Strand.FORWARD);
356      }
357
358      return this;
359   }
360
361   //---------------------------------------------------------------------------
362   public String getRecognitionSequence()
363   {
364      return mRecognitionSequence;
365   }
366
367
368   //--------------------------------------------------------------------------
369   /**
370    Returns the forward strand cut site indices relative to the start of the motif.
371    * @return Usually one but possibly two cut site indices on the forward strand.
372    */
373   public int[] getFwdStrandCutSiteIndices()
374   {
375      return mFwdStrandCutSiteIndices;
376   }
377
378
379   //--------------------------------------------------------------------------
380   /**
381    Returns the reverse strand cut site indices relative to the start of the motif.
382    * @return Usually one but possibly two cut site indices on the reverse strand.
383    */
384   public int[] getRevStrandCutSiteIndices()
385   {
386      return mRevStrandCutSiteIndices;
387   }
388
389   //---------------------------------------------------------------------------
390   public boolean isPalindromic()
391   {
392      return mIsPalindromic;
393   }
394
395
396   //--------------------------------------------------------------------------
397   @Override
398   public RestrictionEnzyme lock()
399   {
400      return (RestrictionEnzyme) super.lock();
401   }
402
403
404   //--------------------------------------------------------------------------
405   /**
406    Puts the AminoAcid into the Set of unique RestrictionEnzymes returned by RestrictionEnzyme.values().
407    */
408   public RestrictionEnzyme register()
409   {
410      if (! isLocked())
411      {
412         throw new RuntimeException("Only locked RestrictionEnzymes can be added to the values list!");
413      }
414
415      sValues.add(this);
416
417      return this;
418   }
419
420
421   //--------------------------------------------------------------------------
422   /**
423    Returns the RestrictionEnzyme whose name matches the specified String.
424    @param inString the name for the RestrictionEnzyme to retrieve
425    @return the RestrictionEnzyme whose name matches the specified String
426    */
427   public static RestrictionEnzyme valueOf(String inString)
428   {
429      RestrictionEnzyme value = null;
430
431      if (StringUtil.isSet(inString))
432      {
433         for (RestrictionEnzyme enzyme : sValues)
434         {
435            if (enzyme.name().equalsIgnoreCase(inString))
436            {
437               value = enzyme;
438               break;
439            }
440         }
441      }
442
443      return value;
444   }
445
446   //--------------------------------------------------------------------------
447   public static RestrictionEnzyme[] values()
448   {
449      return sValues.toArray(new RestrictionEnzyme[sValues.size()]);
450   }
451
452   //###########################################################################
453   // PROTECTED METHODS
454   //###########################################################################
455
456   //--------------------------------------------------------------------------
457   @Override
458   protected RestrictionSite createMatch(String inSeq, SeqLocation inLocation)
459   {
460      return new RestrictionSite(this, inSeq, inLocation);
461   }
462
463   //---------------------------------------------------------------------------
464   protected void setIsPalindromic(boolean inValue)
465   {
466      mIsPalindromic = inValue;
467   }
468
469   //###########################################################################
470   // PRIVATE METHODS
471   //###########################################################################
472
473   //--------------------------------------------------------------------------
474   private String extractPrositePattern()
475   {
476      String patternString = mRecognitionSequence;
477
478      List<Integer> forwardCutSiteIndicesList = new ArrayList<>(2);
479      List<Integer> reverseCutSiteIndicesList = new ArrayList<>(2);
480
481      boolean isPalindromic = true;
482
483      Matcher m = s5PrimeNonPalindromicCutSpecPattern.matcher(patternString);
484      if (m.find())
485      {
486         forwardCutSiteIndicesList.add(- Integer.parseInt(m.group(1)) - 1);
487         reverseCutSiteIndicesList.add(- Integer.parseInt(m.group(2)) - 1);
488         patternString = patternString.substring(m.group().length());
489         isPalindromic = false;
490      }
491
492      m = s3PrimeNonPalindromicCutSpecPattern.matcher(patternString);
493      if (m.find())
494      {
495         patternString = patternString.substring(0, patternString.length() - m.group().length());
496         forwardCutSiteIndicesList.add(patternString.length() + Integer.parseInt(m.group(1)));
497         reverseCutSiteIndicesList.add(patternString.length() + Integer.parseInt(m.group(2)));
498         isPalindromic = false;
499      }
500
501      StringBuilderPlus prositePattern = new StringBuilderPlus().setDelimiter("-");
502
503      for (int i = 0; i < patternString.length(); i++)
504      {
505         char theChar = patternString.charAt(i);
506
507         if (theChar == '/')
508         {
509            forwardCutSiteIndicesList.add(i);
510            forwardCutSiteIndicesList.add(patternString.length() - i - 1);
511         }
512         else
513         {
514            prositePattern.delimitedAppend(theChar);
515         }
516      }
517
518      prositePattern.append(".");
519      
520      mFwdStrandCutSiteIndices = new int[forwardCutSiteIndicesList.size()];
521      for (int i = 0; i < forwardCutSiteIndicesList.size(); i++)
522      {
523         mFwdStrandCutSiteIndices[i] = forwardCutSiteIndicesList.get(i);
524      }
525
526      if (CollectionUtil.hasValues(reverseCutSiteIndicesList))
527      {
528         mRevStrandCutSiteIndices = new int[reverseCutSiteIndicesList.size()];
529         for (int i = 0; i < reverseCutSiteIndicesList.size(); i++)
530         {
531            mRevStrandCutSiteIndices[i] = reverseCutSiteIndicesList.get(i);
532         }
533      }
534
535      setIsPalindromic(isPalindromic);
536
537      return prositePattern.toString();
538   }
539}