001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 * Created on Jun 4, 2010 021 * Author: Jianjiong Gao 022 * 023 */ 024 025package org.biojava.nbio.protmod; 026 027import java.util.*; 028 029/** 030 * contains information about a certain Component. 031 * The Component class uses the extensible enum pattern. 032 * You can't instantiate Component directly, instead 033 * you have to use one of the {@link register} and {@link of} methods. 034 * 035 * @author Jianjiong Gao 036 * @since 3.0 037 */ 038public final class Component { 039 private final Set<String> pdbccIds; 040 private final boolean isNTerminal; 041 private final boolean isCTerminal; 042 043 private static Set<Component> components = null; 044 private static Map<Set<String>, Component> nonTerminalComps = null; 045 private static Map<Set<String>, Component> nTerminalAminoAcids = null; 046 private static Map<Set<String>, Component> cTerminalAminoAcids = null; 047 048 /** 049 * Lazy initialization of the static variables. 050 */ 051 private static void lazyInit() { 052 if (components==null) { 053 components = new HashSet<Component>(); 054 nonTerminalComps = new HashMap<Set<String>, Component>(); 055 nTerminalAminoAcids = new HashMap<Set<String>, Component>(); 056 cTerminalAminoAcids = new HashMap<Set<String>, Component>(); 057 } 058 } 059 060 /** 061 * Create a ComponentImpl. 062 * @param pdbccIds a set of possible Protein Data Bank ID. Cannot be null or empty. 063 * @param isNTerminal true if occurring at N-terminal. false, otherwise. 064 * @param isCTerminal true if occurring at C-terminal. false, otherwise. 065 * @throws IllegalArgumentException if pdbccId or type is null, 066 * or terminal condition is indicated for non-amino-acid component, 067 * or both N-terminal and C-terminal are true. 068 */ 069 private Component(final Set<String> pdbccIds, 070 final boolean isNTerminal, final boolean isCTerminal) { 071 if (pdbccIds==null || pdbccIds.isEmpty()) { 072 throw new IllegalArgumentException("pdbccId or type cannot be null."); 073 } 074 075 if (isNTerminal&&isCTerminal) { 076 throw new IllegalArgumentException("An amino acid can be specified at" + 077 "N-terminal or C-terminal but not both."); //TODO: is this true? 078 } 079 080 this.pdbccIds = pdbccIds; 081 this.isNTerminal = isNTerminal; 082 this.isCTerminal = isCTerminal; 083 } 084 085 /** 086 * 087 * @return Protein Data Bank ID. 088 */ 089 public Set<String> getPdbccIds() { 090 return pdbccIds; 091 } 092 093 /** 094 * 095 * @return true if occurring on N terminal; false, otherwise. 096 */ 097 public boolean isNTerminal() { 098 return isNTerminal; 099 } 100 101 /** 102 * 103 * @return true if occurring on C terminal; false, other wise. 104 */ 105 public boolean isCTerminal() { 106 return isCTerminal; 107 } 108 109 /** 110 * Get a Component that does not have to occur at terminals. If the 111 * corresponding component has already been registered, return that one. 112 * @param pdbccIds possible Protein Data Bank ID. 113 * @return a component. 114 * @throws IllegalArgumentException if pdbccId or type is null, 115 * or the pdbccId has been registered as a different type. 116 */ 117 public static Component of(final String pdbccId) { 118 return of(pdbccId, false, false); 119 } 120 121 /** 122 * Get or create a Component. 123 * @param pdbccId Protein Data Bank ID. 124 * @param isNTerminal true if occurring at N-terminal. false, otherwise. 125 * @param isCTerminal true if occurring at C-terminal. false, otherwise. 126 * @return a component. 127 * @throws IllegalArgumentException if pdbccId or type is null, 128 * or the pdbccId has been registered as a different type, 129 * or terminal condition is indicated for non-amino-acid component, 130 * or both N-terminal and C-terminal are true. 131 */ 132 public static Component of(final String pdbccId, 133 final boolean isNTerminal, final boolean isCTerminal) { 134 return of (Collections.singleton(pdbccId), isNTerminal, isCTerminal); 135 } 136 137 /** 138 * Get a Component that does not have to occur at terminals. If the 139 * corresponding component has already been registered, return that one. 140 * @param pdbccIds a set of possible Protein Data Bank ID. 141 * @return a component. 142 * @throws IllegalArgumentException if pdbccId or type is null, 143 * or the pdbccId has been registered as a different type. 144 */ 145 public static Component of(final Set<String> pdbccIds) { 146 return of(pdbccIds, false, false); 147 } 148 149 /** 150 * Get or create a Component. 151 * @param pdbccIds a set of possible Protein Data Bank ID. 152 * @param isNTerminal true if occurring at N-terminal. false, otherwise. 153 * @param isCTerminal true if occurring at C-terminal. false, otherwise. 154 * @return a component. 155 * @throws IllegalArgumentException if pdbccId or type is null, 156 * or the pdbccId has been registered as a different type, 157 * or terminal condition is indicated for non-amino-acid component, 158 * or both N-terminal and C-terminal are true. 159 */ 160 public static Component of(final Set<String> pdbccIds, 161 final boolean isNTerminal, final boolean isCTerminal) { 162 if (isNTerminal && isCTerminal) { 163 throw new IllegalArgumentException("An amino acid can be at" + 164 "N-terminal or C-terminal but not both."); //TODO: is this true? 165 } 166 167 lazyInit(); 168 169 Component comp; 170 if (isNTerminal) { 171 comp = nTerminalAminoAcids.get(pdbccIds); 172 if (comp == null) { 173 comp = new Component(pdbccIds, isNTerminal, isCTerminal); 174 nTerminalAminoAcids.put(pdbccIds, comp); 175 } 176 } else if (isCTerminal) { 177 comp = cTerminalAminoAcids.get(pdbccIds); 178 if (comp == null) { 179 comp = new Component(pdbccIds, isNTerminal, isCTerminal); 180 cTerminalAminoAcids.put(pdbccIds, comp); 181 } 182 } else { 183 comp = nonTerminalComps.get(pdbccIds); 184 if (comp == null) { 185 comp = new Component(pdbccIds, isNTerminal, isCTerminal); 186 nonTerminalComps.put(pdbccIds, comp); 187 } 188 } 189 190 components.add(comp); 191 return comp; 192 } 193 194 public static Set<Component> allComponents() { 195 return Collections.unmodifiableSet(components); 196 } 197 198 /** 199 * 200 * @return informative description. 201 */ 202 @Override 203 public String toString() { 204 StringBuilder sb = new StringBuilder(); 205 sb.append(getPdbccIds()); 206 if (isCTerminal()) { 207 sb.append("(C)"); 208 } else if (isNTerminal()) { 209 sb.append("(N)"); 210 } 211 return sb.toString(); 212 } 213}