/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * * Created on Jun 5, 2010 * Author: Jianjiong Gao * */ package org.biojava.nbio.protmod.structure; import org.biojava.nbio.protmod.ModificationCategory; import org.biojava.nbio.protmod.ProteinModification; import org.biojava.nbio.protmod.ProteinModificationImpl; import org.biojava.nbio.protmod.io.ModifiedCompoundXMLConverter; import java.io.Serializable; import java.util.*; /** * * @author Jianjiong Gao * @since 3.0 */ public class ModifiedCompoundImpl implements ModifiedCompound, Serializable, Comparable<ModifiedCompound> { /** * */ private static final long serialVersionUID = 1656563037849815427L; ProteinModification originalModification; ProteinModification modification; Set<StructureGroup> groups; Map<Set<StructureGroup>, Set<StructureAtomLinkage>> atomLinkages; public static final String newline = System.getProperty("line.separator"); public ModifiedCompoundImpl(){ } /** * Create a ModifiedCompoundImpl that has only one involved component. * Use this constructor for a modified residue. * @param modification {@link ProteinModification}. * @param modifiedResidue modified group. * @return a {@link ModifiedCompound}. * @throws IllegalArgumentException if either argument is null. */ public ModifiedCompoundImpl ( ProteinModification modification, StructureGroup modifiedResidue) { if (modification==null || modifiedResidue==null) { throw new IllegalArgumentException("Null argument(s)"); } groups = new HashSet<StructureGroup>(1); groups.add(modifiedResidue); // is it possible that components be added by addLinkage later? atomLinkages = null; setModification(modification); } /** * * @param modification ProteinModification. * @param linkages a collection of atom linkages. * @see ProteinModification * @see StructureAtomLinkage */ public ModifiedCompoundImpl( ProteinModification modification, Collection<StructureAtomLinkage> linkages) { if (modification==null) { throw new IllegalArgumentException("modification cannot be null"); } if (linkages==null||linkages.isEmpty()) { throw new IllegalArgumentException("at least one linkage."); } this.groups = new HashSet<StructureGroup>(); addAtomLinkages(linkages); setModification(modification); } @Override public void setModification(ProteinModification protmod){ originalModification = protmod; resetModification(); } @Override public ProteinModification getModification() { return modification; } private void resetModification() { if (originalModification == null) modification = originalModification; else if (originalModification.getCategory()!=ModificationCategory.UNDEFINED) modification = originalModification; else { int nRes = 0; Set<String> ligands = new HashSet<String>(); for (StructureGroup group : groups) { if (group.isAminoAcid()) { nRes ++; } else { ligands.add(group.getPDBName().trim()); } } ModificationCategory cat; switch (nRes) { case 0: modification = originalModification; return; case 1: cat = ModificationCategory.ATTACHMENT; break; case 2: cat = ModificationCategory.CROSS_LINK_2; break; case 3: cat = ModificationCategory.CROSS_LINK_3; break; case 4: cat = ModificationCategory.CROSS_LINK_4; break; case 5: cat = ModificationCategory.CROSS_LINK_5; break; case 6: cat = ModificationCategory.CROSS_LINK_6; break; case 7: cat = ModificationCategory.CROSS_LINK_7; break; default: cat = ModificationCategory.CROSS_LINK_8_OR_LARGE; break; } modification = new ProteinModificationImpl.Builder(originalModification) .setCategory(cat).addKeywords(ligands).build(); } } /** * * @return the original modification ID. * @deprecated use getModification().getId() */ @Deprecated public String getOriginalModificationId() { if (originalModification==null) return null; return originalModification.getId(); } @Override public Set<StructureGroup> getGroups() { if ( groups == null) return null; return Collections.unmodifiableSet(groups); } @Override public Set<StructureGroup> getGroups(boolean isAminoAcid) { Set<StructureGroup> result = new HashSet<StructureGroup>(); for (StructureGroup group : groups) { if (group.isAminoAcid() == isAminoAcid) { result.add(group); } } return result; } @Override public void setGroups(Set<StructureGroup> groups){ this.groups = groups; resetModification(); } @Override public Set<StructureAtomLinkage> getAtomLinkages() { if (atomLinkages==null) { return Collections.emptySet(); } else { Set<StructureAtomLinkage> result = new HashSet<StructureAtomLinkage>(); for (Set<StructureAtomLinkage> linkages : atomLinkages.values()) { result.addAll(linkages); } return result; } } @Override public void setAtomLinkages(Set<StructureAtomLinkage> linkages) { for (StructureAtomLinkage sali : linkages){ addAtomLinkage(sali); } resetModification(); } @Override public boolean addAtomLinkage(StructureAtomLinkage linkage) { if (linkage==null) { throw new IllegalArgumentException("Null linkage"); } Set<StructureGroup> gs = new HashSet<StructureGroup>(2); gs.add(linkage.getAtom1().getGroup()); gs.add(linkage.getAtom2().getGroup()); if (atomLinkages==null) { atomLinkages = new HashMap<Set<StructureGroup>, Set<StructureAtomLinkage>>(); } Set<StructureAtomLinkage> linkages = atomLinkages.get(gs); if (linkages == null) { linkages = new HashSet<StructureAtomLinkage>(); atomLinkages.put(gs, linkages); groups.addAll(gs); // it's possible of new groups }; return linkages.add(linkage); } @Override public void addAtomLinkages(Collection<StructureAtomLinkage> linkages) { if (linkages==null) { throw new IllegalArgumentException("Null linkages"); } for (StructureAtomLinkage link : linkages) { addAtomLinkage(link); } resetModification(); } @Override public boolean crossChains() { if (groups==null || groups.isEmpty()) return false; Iterator<StructureGroup> it = groups.iterator(); String chain = it.next().getChainId(); while (it.hasNext()) { if (!it.next().getChainId().equals(chain)) return true; } return false; } @Override public String toString(){ StringBuilder sb = new StringBuilder(); if ( originalModification == null) return "ModifiedCompoundImpl -- not initialized"; //sb.append("Modification_"); sb.append(originalModification.getId()); ModificationCategory cat ; if (originalModification.getCategory()==ModificationCategory.UNDEFINED) { cat = getModification().getCategory(); } else cat = originalModification.getCategory(); sb.append("_"); sb.append(cat.toString()); return sb.toString(); } @Override public String getDescription() { StringBuilder sb = new StringBuilder(); //sb.append("Category: "); if ( getModification() == null) { sb.append(" !!! not initialized !!!"); return sb.toString(); } sb.append(originalModification.toString()); // sb.append(getModification().getCategory()); // if (!modification.getKeywords().isEmpty()) { // sb.append("; "); // sb.append(modification.getKeywords()); // } // sb.append("; Modification ID: "); // sb.append(modification.getId()); // // if (modification.getResidId()!=null) { // sb.append("; RESID: "); // sb.append(modification.getResidId()); // sb.append(" ["); // sb.append(modification.getResidName()); // sb.append(']'); // } // // sb.append(" | "); // // if (atomLinkages==null) { // for (StructureGroup group : groups) { // sb.append(group); // sb.append(" | "); // } // } else { // for (Set<StructureAtomLinkage> linkages : atomLinkages.values()) { // for (StructureAtomLinkage linkage : linkages) { // sb.append(linkage); // sb.append(" | "); // } // } // } return sb.toString(); } @Override public void setDescription(String desc){ // do nothing.... } @Override public int compareTo(ModifiedCompound compound){ try { // quite complex objects so the easiest is to just wrap it as XML // and compare the two strings... String xml = ModifiedCompoundXMLConverter.toXML(this); String xml2 = ModifiedCompoundXMLConverter.toXML(compound); return xml.compareTo(xml2); } catch (Exception e){ } return this.toString().compareTo(compound.toString()); } /** * @return true if same modification and same components; false, otherwise. */ @Override public boolean equals(Object obj) { if (!(obj instanceof ModifiedCompound)) { return false; } ModifiedCompound mci = (ModifiedCompound)obj; if (mci.getModification() != originalModification) { return false; } if (!groups.equals(mci.getGroups())) { return false; } return true; // Do not need to consider linkage, since they can be determined by // modification and groups. } @Override public int hashCode() { int result = 17; result = result * 32 + originalModification.hashCode(); int sum = 0; for (StructureGroup group : groups) { sum += group.hashCode(); } result = result * 32 + sum; return result; } }