Java tutorial
/*-- * * @(#) GraphSynchronizer.java * * Copyright 2013 by Roche Diagnostics GmbH, * Nonnenwald 2, DE-82377 Penzberg, Germany * All rights reserved. * * This software is the confidential and proprietary information * of Roche Diagnostics GmbH ("Confidential Information"). You * shall not disclose such Confidential Information and shall use * it only in accordance with the terms of the license agreement * you entered into with Roche Diagnostics GmbH. * */ package org.roche.antibody.services.graphsynchronizer; import java.io.FileNotFoundException; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.swing.JOptionPane; import javax.swing.UIManager; import javax.swing.plaf.FontUIResource; import org.apache.commons.configuration.Configuration; import org.helm.editor.controller.ModelController; import org.helm.editor.data.MonomerStoreCache; import org.helm.editor.editor.MacromoleculeEditor; import org.helm.notation.MonomerFactory; import org.helm.notation.MonomerStore; import org.helm.notation.model.Attachment; import org.helm.notation.model.Monomer; import org.helm.notation.tools.ComplexNotationParser; import org.helm.notation.tools.PeptideSequenceParser; import org.helm.notation.tools.SimpleNotationParser; import org.helm.notation.tools.StructureParser; import org.roche.antibody.model.antibody.Antibody; import org.roche.antibody.model.antibody.ChemElement; import org.roche.antibody.model.antibody.Connection; import org.roche.antibody.model.antibody.CysteinConnection; import org.roche.antibody.model.antibody.Domain; import org.roche.antibody.model.antibody.GeneralConnection; import org.roche.antibody.model.antibody.Peptide; import org.roche.antibody.model.antibody.RNA; import org.roche.antibody.model.antibody.Sequence; import org.roche.antibody.services.AbstractGraphService; import org.roche.antibody.services.ConnectionService; import org.roche.antibody.services.DomainService; import org.roche.antibody.services.PreferencesService; import org.roche.antibody.services.SequenceService; import org.roche.antibody.services.antibody.AntibodyService; import org.roche.antibody.services.helmnotation.HELM; import org.roche.antibody.services.helmnotation.HelmNotationService; import org.roche.antibody.services.helmnotation.model.HELMChem; import org.roche.antibody.services.helmnotation.model.HELMCode; import org.roche.antibody.services.helmnotation.model.HELMConnection; import org.roche.antibody.services.helmnotation.model.HELMElement; import org.roche.antibody.services.helmnotation.model.HELMPeptide; import org.roche.antibody.services.helmnotation.model.HELMRna; import org.roche.antibody.ui.abstractgraph.view.DomainAnnotationAction; import org.roche.antibody.ui.components.AntibodyEditorAccess; import org.roche.antibody.ui.components.AntibodyEditorPane; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import y.base.NodeMap; import y.layout.hierarchic.GivenLayersLayerer; import com.quattroresearch.blastws.BlastSearchParams; import com.quattroresearch.blastws.BlastSearchService; /** * {@code GraphSynchronizer} The Magic begins here ... :) This class is responsible for synchronizing the state between * the MacromolecularEditor and the AntibodyEditor. This service is STATEFUL, assure that each time you start a * synchroni * * me = MacromolecularEditor * * @author <a href="mailto:Stefan.Klostermann@roche.com">Stefan Klostermann</a>, Roche Pharma Research and Early * Development - Informatics, Roche Innovation Center Penzberg * @author <a href="mailto:stefan_dieter.zilch@contractors.roche.com">Stefan Zilch</a> * @version $Id: GraphSynchronizer.java 13993 2014-12-12 12:30:53Z schirmb $ */ public class GraphSynchronizer { private static final String NEW_PEPTIDE_DEFAULT_NAME = "Peptide"; /** The Logger for this class */ private static final Logger LOG = LoggerFactory.getLogger(GraphSynchronizer.class); private static final String CBLOCK_MONOMER_NAME = "C-BLOCK"; private static final String CBLOCK_MONOMER_SMILES = "C[*] |$;_R1$|"; private static final String CBLOCK_MOLFILE = "H4sIAAAAAAAAAI2OsQ7CQAxD93yFpbL2lOS4XjNTxFSEOrAzdunQge8n10qlCAYsD5YdPYWA/jE/xwkQlSxRcmTtsIkIUB8B3vktM8NdmdnvUMeQmqSlV0/xWBIHXxknfCJ+e6FoaBPnlWI52Y4yVH9S5Ptt6oHhclvaMkJKc752RAcXvQDuchVTDAEAAA=="; private static final String NBLOCK_MONOMER_NAME = "N-BLOCK"; private static final String NBLOCK_MONOMER_SMILES = CBLOCK_MONOMER_SMILES; private static final String NBLOCK_MOLFILE = "H4sIAAAAAAAAAI2OsQ7CQAxD93yFJbpySnI9QmaKOhVVHdgZWRgY+H5yrQRFMGB5sOzoKQQMl/vjegNExSSLqWmHl4gAjRHgld9yd5yVmeMO25zKrmjtNVJua+IUK+OAT8RvzxRN+8K2UNyKryjT5k+KfL9NAzD149zWEVKb46kjakL0BMIa+YcMAQAA"; private static final String CYSBLOCK_MONOMER_NAME = "CYS-BLOCK"; private static final String CYSBLOCK_MONOMER_SMILES = CBLOCK_MONOMER_SMILES; private static final String CYSBLOCK_MOLFILE = "H4sIAAAAAAAAAI2OsQ7CQAxD93yFpbL2lOS4XjNTxFSEOrAzdunQge8n10qlCAYsD5YdPYWA/jE/xwkQlSxRchTtsIkIUB8B3vktM8NdmdnvUMeQmqSlV0/xWBIHXxknfCJ+e6FoaBPnlWI52Y4yVH9S5Ptt6oHhclvaMkJKc752RAcXvQCfYEm6DAEAAA=="; private static final String BLOCKS_MONOMER_TYPE = Monomer.UNDEFINED_MOMONER_TYPE; private static final String BLOCKS_POLYMER_TYPE = Monomer.PEPTIDE_POLYMER_TYPE; /** The MacromolecularEditor of HELM Editor */ private MacromoleculeEditor me; private AntibodyEditorPane abEditor; private String helmSentToEditor; private Antibody ab; private Domain activeDomain; private List<Connection> handledConnections = new ArrayList<Connection>(); private List<Connection> handledInterDomainConnections = new ArrayList<Connection>(); private List<Sequence> handledSequences = new ArrayList<Sequence>(); private DomainService domainService = DomainService.getInstance(); private ConnectionService connectionService = ConnectionService.getInstance(); private SequenceService seqService = SequenceService.getInstance(); private int deletedConnectionCount; private int createdConnectionCount; /** * if we add a blocker we count the number of block. in order to check if the user removed a blocker during edit phase */ private int blockerCount; /** * if we edit a domain, we have to add logical blocker to the n- and c-terminals. if we sync the domain back, we have * to remove the blocker. so we store them here. */ List<String> blocksToRemove = new ArrayList<String>(); private Configuration appPrefs; public GraphSynchronizer(MacromoleculeEditor mainEditor, AntibodyEditorPane abEditor, Antibody ab) { this.me = mainEditor; this.abEditor = abEditor; this.ab = ab; appPrefs = PreferencesService.getInstance().getApplicationPrefs(); blocksToRemove.add(appPrefs.getString(PreferencesService.C_BLOCKER)); blocksToRemove.add(appPrefs.getString(PreferencesService.N_BLOCKER)); blocksToRemove.add(appPrefs.getString(PreferencesService.CYS_BLOCKER)); } /** * * @param domain * @throws Exception */ public void sendToMacroMolecularEditor(Domain domain) throws Exception { sendToMacroMolecularEditor(domain, null); } /*** * Registers a block monomer in local helm editor store and returns success. * * @param monomerName * @param smiles * @param molfile * @return number of registered block monomers * @throws Exception */ private int registerBlockMonomerInLocalStore(String monomerName, String smiles, String molfile) throws Exception { MonomerFactory factory = MonomerFactory.getInstance(); MonomerStore store = factory.getMonomerStore(); if (!store.getMonomerDB().get("CHEM").containsKey(monomerName)) { chemaxon.struc.Molecule mol = StructureParser.getMolecule(smiles); Monomer m = new Monomer(Monomer.CHEMICAL_POLYMER_TYPE, Monomer.UNDEFINED_MOMONER_TYPE, "", monomerName); m.setMolfile(molfile); m.setName(monomerName); m.setCanSMILES(smiles); if (monomerName.equals(CBLOCK_MONOMER_NAME)) { List<Attachment> attachmentList = new ArrayList<Attachment>(); Attachment attachment = new Attachment("R1", "H"); attachment.setAlternateId("R1-H"); attachmentList.add(attachment); m.setAttachmentList(attachmentList); } else if (monomerName.equals(NBLOCK_MONOMER_NAME)) { List<Attachment> attachmentList = new ArrayList<Attachment>(); Attachment attachment = new Attachment("R1", "OH"); attachment.setAlternateId("R1-OH"); attachmentList.add(attachment); m.setAttachmentList(attachmentList); } else if (monomerName.equals(CYSBLOCK_MONOMER_NAME)) { List<Attachment> attachmentList = new ArrayList<Attachment>(); Attachment attachment = new Attachment("R1", "X"); attachment.setAlternateId("R1-X"); attachmentList.add(attachment); m.setAttachmentList(attachmentList); } store.addMonomer(m, true); factory.saveMonomerCache(); return 1; } return 0; } /** * @param domain * @param additionalSequence A sequence that should be added to the panel as well. * @throws Exception */ public void sendToMacroMolecularEditor(Domain domain, String additionalSequence) throws Exception { int registered = registerBlockMonomerInLocalStore(CBLOCK_MONOMER_NAME, CBLOCK_MONOMER_SMILES, CBLOCK_MOLFILE); registered += registerBlockMonomerInLocalStore(NBLOCK_MONOMER_NAME, NBLOCK_MONOMER_SMILES, NBLOCK_MOLFILE); registered += registerBlockMonomerInLocalStore(CYSBLOCK_MONOMER_NAME, CYSBLOCK_MONOMER_SMILES, CYSBLOCK_MOLFILE); if (registered > 0) { LOG.debug(registered + " BLOCK monomers were registered. Polymer panels will be updated."); me.updatePolymerPanels(); } this.activeDomain = domain; HELMCode code = buildHelm(domain); addBlocker(code, domain); String helmNotation = HelmNotationService.getInstance().toHELMString(code); this.helmSentToEditor = helmNotation; ModelController.notationUpdated(helmNotation, me.getOwnerCode()); // // if (additionalSequence != null) { try { String existingNotation = this.me.getNotation(); String simpleNotation = PeptideSequenceParser.getNotation(additionalSequence); String complexNotation = SimpleNotationParser.getComplextNotationForPeptide(simpleNotation); String newNotation = null; if (existingNotation != null && existingNotation.trim().length() > 0) { newNotation = ComplexNotationParser.getCombinedComlexNotation(existingNotation, complexNotation); } else newNotation = complexNotation; me.synchronizeZoom(); ModelController.notationUpdated(newNotation, me.getOwnerCode()); } catch (Exception e) { JOptionPane.showMessageDialog(this.abEditor, "Adding the domain failed."); e.printStackTrace(); } } } private HELMCode buildHelm(Domain activeDomain) { HELMCode code = new HELMCode(); Deque<Sequence> sequencesToHandle = new ArrayDeque<Sequence>(); handledConnections.clear(); handledInterDomainConnections.clear(); handledSequences.clear(); sequencesToHandle.offer(activeDomain); Map<Sequence, HELMElement> helmElemMap = new HashMap<Sequence, HELMElement>(); while (sequencesToHandle.isEmpty() == false) { Sequence seqToHandle = sequencesToHandle.poll(); Sequence seqForConnectionCheck = seqToHandle; if (handledSequences.contains(seqToHandle)) { continue; } else { handledSequences.add(seqToHandle); } if (seqToHandle instanceof Domain) { activeDomain = (Domain) seqToHandle; HELMElement pep = seqService.toHELM(activeDomain); code.addHELMElement(pep); helmElemMap.put(activeDomain.getPeptide(), pep); seqForConnectionCheck = activeDomain.getPeptide(); } for (Connection con : seqToHandle.getConnections()) { if (handledConnections.contains(con)) { continue; } if (con instanceof GeneralConnection) { HELMConnection helmCon = null; if (con.getSource() == seqForConnectionCheck && con.getTarget() == seqForConnectionCheck) { HELMElement element = seqService.toHELM(seqToHandle); code.addHELMElement(element); helmCon = connectionService.createConnection(con, element, element); } else { HELMElement source = helmElemMap.get(con.getSource()); if (source == null) { source = seqService.toHELM(con.getSource()); helmElemMap.put(con.getSource(), source); code.addHELMElement(source); sequencesToHandle.push(con.getSource()); } HELMElement target = helmElemMap.get(con.getTarget()); if (target == null) { target = seqService.toHELM(con.getTarget()); helmElemMap.put(con.getTarget(), target); code.addHELMElement(target); sequencesToHandle.push(con.getTarget()); } helmCon = connectionService.createConnection(con, source, target); } code.addHELMConnection(helmCon); handledConnections.add(con); } if (con instanceof CysteinConnection && connectionService.isIntraDomainConnection(con)) { HELMConnection helmCon = connectionService.createConnection(con, helmElemMap.get(activeDomain.getPeptide()), helmElemMap.get(activeDomain.getPeptide())); handledConnections.add(con); code.addHELMConnection(helmCon); } if (con instanceof CysteinConnection && !connectionService.isIntraDomainConnection(con)) { handledInterDomainConnections.add(con); } } } return code; } /** * Syncs the changes back to the antibody and returns whether changes should be submitted (and the macromolecule * editor cleared) * * @param helmCode * @return true when macromolecule editor should be cleared and the antibody synced back to abEditor. False when sync * should be cancelled for further edit. * @throws FileNotFoundException */ public boolean syncBackToAntibody(String helmCode) throws FileNotFoundException { Map<HELMElement, Sequence> helmToSequence = new HashMap<HELMElement, Sequence>(); HELMCode code = HelmNotationService.getInstance().toHELMCode(helmCode); List<HELMElement> handledElements = new ArrayList<HELMElement>(); deletedConnectionCount = 0; createdConnectionCount = 0; // do not change anything, when molecule did not change try { if (ComplexNotationParser.getCanonicalNotation(helmSentToEditor) .equals(ComplexNotationParser.getCanonicalNotation(helmCode))) { return true; } } catch (Exception e) { LOG.error(e.getMessage()); } int validationOption = validate(code); if (validationOption == JOptionPane.YES_OPTION) { removeBlocker(code); deleteOldSequencesAndConnections(); handleActiveDomain(code, helmToSequence, handledElements); handleNewSequences(code, helmToSequence, handledElements); handleNewConnections(code, helmToSequence); // align non-domain Sequences, after they were created and connected AbstractGraphService.alignNonDomainSequences(abEditor.getAbstractGraph(), ab, (NodeMap) abEditor.getAbstractGraph().getDataProvider(GivenLayersLayerer.LAYER_ID_KEY)); abEditor.updateLayoutHints(); abEditor.updateGraphLayout(); } else { // if (validationOption == JOptionPane.CANCEL_OPTION) { return false; } else if (validationOption == JOptionPane.NO_OPTION) { return true; } } try { DomainAnnotationAction.annotateDomain(AntibodyEditorAccess.getInstance().getAntibodyEditorPane(), activeDomain); } catch (FileNotFoundException e) { e.printStackTrace(); } // Show the user an appropriate message when the connection count // changed. int connectionCountChange = deletedConnectionCount - createdConnectionCount; if (connectionCountChange > 0) { String message = String.format("%d %s removed, because automated reconfiguration is not possible.", connectionCountChange, connectionCountChange > 1 ? "connections" : "connection"); JOptionPane.showMessageDialog(this.abEditor, message, "Connection count changed", JOptionPane.INFORMATION_MESSAGE); } else if (connectionCountChange < 0) { String message = String.format("%d %s additional connections added.", -connectionCountChange, connectionCountChange < -1 ? "connections" : "connection"); JOptionPane.showMessageDialog(this.abEditor, message, "Connection count changed", JOptionPane.INFORMATION_MESSAGE); } return true; } private void deleteOldSequencesAndConnections() { for (Connection con : handledConnections) { if (con instanceof CysteinConnection) { deletedConnectionCount++; } ab.removeConnection(con); AbstractGraphService.removeConnection(abEditor.getAbstractGraph(), con); } for (Connection con : handledInterDomainConnections) { if (con instanceof CysteinConnection) { deletedConnectionCount++; } ab.removeConnection(con); AbstractGraphService.removeConnection(abEditor.getAbstractGraph(), con); } for (Sequence seq : handledSequences) { if (seq != activeDomain) { AntibodyService.getInstance().removeSequence(seq, ab); AbstractGraphService.removeSequence(abEditor.getAbstractGraph(), seq); } } } private void handleActiveDomain(HELMCode code, Map<HELMElement, Sequence> helmToSequence, List<HELMElement> handledElemetns) throws FileNotFoundException { // we handle the activeDomain and their connections HELMElement elemOfActiveDomain = HelmNotationService.getInstance().getHELMElementByName("PEPTIDE1", code); if (elemOfActiveDomain != null) { HELMPeptide curPeptide = (HELMPeptide) elemOfActiveDomain; helmToSequence.put(curPeptide, activeDomain); handledElemetns.add(curPeptide); Domain dom = DomainService.getInstance().identifyNewDomain(activeDomain, curPeptide.getSimpleSequence()); if (dom != null) { adaptHELMCodeForSyncBack(dom, curPeptide, code, handledElemetns, helmToSequence); AbstractGraphService.addSequence(abEditor.getAbstractGraph(), dom); } } } /** * Validates in order to decide, if we can sync our model back or not! * * @param code * @return JOptionPane.YES_NO_CANCEL_OPTION */ private int validate(HELMCode code) { int blockersInCode = 0; boolean activeDomainDetected = false; boolean activeDomainChanged = false; String domainChangesMsg = ""; for (HELMElement elem : code.getAllElements()) { if (blocksToRemove.contains(elem.getSequenceRepresentation())) { blockersInCode++; } if (elem instanceof HELMPeptide) { HELMPeptide pep = (HELMPeptide) elem; if (pep.getSimpleSequence().startsWith(activeDomain.getSequence()) || pep.getSimpleSequence().endsWith(activeDomain.getSequence())) { activeDomainDetected = true; } else { domainChangesMsg = checkForSequenceChanges(activeDomain.getSequence(), pep.getSimpleSequence()); activeDomainChanged = true; } } } if (blockersInCode != blockerCount) { JOptionPane.showMessageDialog(me.getFrame(), "Blockers were mainpulated! Model cannot be sync back!", "Sync Error", JOptionPane.ERROR_MESSAGE); return JOptionPane.CANCEL_OPTION; } else if (!activeDomainDetected && activeDomainChanged) { FontUIResource defaultFont = (FontUIResource) UIManager.get("OptionPane.messageFont"); UIManager.put("OptionPane.messageFont", new FontUIResource("Courier New", FontUIResource.PLAIN, 13)); int isConfirmed = JOptionPane.showConfirmDialog(me.getFrame(), domainChangesMsg, "Sequence has changed", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); UIManager.put("OptionPane.messageFont", defaultFont); return isConfirmed; } return JOptionPane.YES_OPTION; } /** * This method checks for changes between 2 sequences and returns a user friendly html message, describing those * changes. * * @param oldSequence * @param newSequence * @return html message */ private String checkForSequenceChanges(String oldSequence, String newSequence) { if (oldSequence.equals(newSequence)) return "<html>Both sequences are equal</html>"; else { String domainChanges = "<html>Sequence between blockers has changed.<br /> Do you want to apply the changes?<br /><br />"; domainChanges += "Length old sequence: " + oldSequence.length() + "AAs<br />"; domainChanges += "Length new sequence: " + newSequence.length() + "AAs<br /><br />"; // Blast for alignment try { BlastSearchService bss = new BlastSearchService(); bss.uploadAndIndex("Protein", 1, ">oldSequence" + System.getProperty("line.separator") + oldSequence); // Set parameters for BLAST BlastSearchParams params = new BlastSearchParams(); params.setQuery(newSequence); params.setSequenceType("Protein"); params.seteValue(1000); params.setWordSize(2); params.setCompBasedStats("F"); bss.searchSequence(params); // <- EXECUTES BLAST domainChanges += bss.getBestAlignment(); } catch (Exception ex) { // no Alignment on Blasterror } return domainChanges; } } private void removeBlocker(HELMCode code) { List<HELMElement> elementsToRemove = new ArrayList<HELMElement>(); for (HELMElement elem : code.getAllElements()) { if (blocksToRemove.contains(elem.getSequenceRepresentation())) { elementsToRemove.add(elem); } } for (HELMElement helmElement : elementsToRemove) { code.removeHELMElement(helmElement); } } private void handleNewConnections(HELMCode code, Map<HELMElement, Sequence> sequenceMap) { for (HELMConnection helmConnection : code.getAllConnections()) { Connection conn = null; if (HelmNotationService.getInstance().isCysteinConnection(helmConnection)) { conn = new CysteinConnectionBuilder().build(canonicalizeHelmConnection(helmConnection), sequenceMap); if (conn != null) { createdConnectionCount++; } } else { conn = new GeneralConnectionBuilder().build(helmConnection, sequenceMap); } if (conn != null && !ab.getConnections().contains(conn)) { ab.addConnection(conn); AbstractGraphService.addConnection(abEditor.getAbstractGraph(), conn); } } } /** * Sorts source and target by position. * * @param connection HelmConnection to canonicalize * @return connection with source and target in correct order */ private HELMConnection canonicalizeHelmConnection(HELMConnection connection) { if (connection.getSourcePosition() > connection.getTargetPosition()) { HELMElement sourceElement = connection.getSource(); int sourcePosition = connection.getSourcePosition(); String sourceRest = connection.getSourceRest(); connection.setSource(connection.getTarget()); connection.setSourcePosition(connection.getTargetPosition()); connection.setSourceRest(connection.getTargetRest()); connection.setTarget(sourceElement); connection.setTargetPosition(sourcePosition); connection.setTargetRest(sourceRest); } return connection; } private List<Sequence> handleNewSequences(HELMCode code, Map<HELMElement, Sequence> helmToSequence, List<HELMElement> handledElements) { List<Sequence> newSequences = new LinkedList<Sequence>(); for (HELMElement element : code.getAllElements()) { if (!handledElements.contains(element)) { Sequence newSequence = null; // handle CHEM if (element instanceof HELMChem) { // ME 2014-10-10: Added SMILES notation to ChemElement. String smiles = ""; String molfile = ""; try { MonomerStore store = MonomerStoreCache.getInstance().getCombinedMonomerStore(); smiles = store.getMonomers("CHEM").get(element.getSequenceRepresentation()).getCanSMILES(); molfile = store.getMonomers("CHEM").get(element.getSequenceRepresentation()).getMolfile(); } catch (Exception e) { LOG.error(e.getMessage(), e); } newSequence = new ChemElement(element.getSequenceRepresentation(), smiles, molfile); AbstractGraphService.addSequence(abEditor.getAbstractGraph(), newSequence); helmToSequence.put(element, newSequence); } if (element instanceof HELMRna) { newSequence = new RNA(element.getSequenceRepresentation()); AbstractGraphService.addSequence(abEditor.getAbstractGraph(), newSequence); helmToSequence.put(element, newSequence); } if (element instanceof HELMPeptide) { // we handle only new peptides not peptide1 because this is // the active domain if (!element.getName().equalsIgnoreCase("PEPTIDE1")) { HELMPeptide hPep = (HELMPeptide) element; Peptide pep = new Peptide(); pep.setName(NEW_PEPTIDE_DEFAULT_NAME); pep.setSequence(hPep.getSimpleSequence()); pep.setOriginalSequence(hPep.getSimpleSequence()); String domainName = DomainService.getInstance().getDefaultName(pep.getSequence()); Domain dom = new Domain(domainName, pep, pep.getStartPosition(), pep.getEndPosition(), pep.getStartPosition(), pep.getEndPosition()); dom.setAntibody(AntibodyEditorAccess.getInstance().getAntibodyEditorPane().getAntibody()); pep.getDomains().add(dom); newSequence = pep; AbstractGraphService.addSequence(abEditor.getAbstractGraph(), dom); helmToSequence.put(element, dom); } } if (newSequence != null) { AntibodyService.getInstance().addSequence(newSequence, ab); handledElements.add(element); newSequences.add(newSequence); } } } return newSequences; } /** * We add blocker in the following logic: * * CASE 0. if only one domain exists no terminal blocks required * * CASE 1. if the domain is at the beginning of a chain, we add a C-Block at the end. * * CASE 2. if the domain is at the end of the chain, we add a N-Block at the beginning. * * CASE 3. if the domain is in the middle of the chain, we add both blocks * * CASE 4. we add CYS-Blocker to all occupied cysteins which are not intra-connected * * @param code * @param dom */ private void addBlocker(HELMCode code, Domain dom) { blockerCount = 0; // handle CASE 2+3 if (dom.getStartPosition() > 1) { addCBlock(code); } // handle CASE 1+3 if (dom.getEndPosition() - dom.getPeptide().getSequence().length() < 0) { addNBlock(code); } // handle CASE 4 List<Integer> cysPositionsToBlock = new ArrayList<Integer>(); for (Connection con : dom.getConnections()) { if (con instanceof CysteinConnection) { if (!connectionService.isIntraDomainConnection(con)) { Sequence realSource = con.getSource(); Sequence realTarget = con.getTarget(); int sPos = con.getSourcePosition(); int tPos = con.getTargetPosition(); if (realSource instanceof Peptide) { Peptide pep = ((Peptide) realSource); realSource = pep.getDomain(con.getSourcePosition()); sPos = domainService.transformPeptidePositionToDomainPosition(pep, sPos); } if (realTarget instanceof Peptide) { Peptide pep = ((Peptide) realTarget); realTarget = pep.getDomain(con.getTargetPosition()); tPos = domainService.transformPeptidePositionToDomainPosition(pep, tPos); } if (realSource == dom) { cysPositionsToBlock.add(sPos); } if (realTarget == dom) { cysPositionsToBlock.add(tPos); } } } } addCysBlocks(cysPositionsToBlock, code); // CASE 0 -> nothing to do. } private void addCysBlocks(List<Integer> cysPositionsToBlock, HELMCode code) { HELMPeptide peptide = (HELMPeptide) HelmNotationService.getInstance().getHELMElementByName("PEPTIDE1", code); for (Integer integer : cysPositionsToBlock) { HELMElement cysBlock = new HELMChem(appPrefs.getString(PreferencesService.CYS_BLOCKER)); HELMConnection con = new HELMConnection(peptide, integer, HELM.R3, cysBlock, 1, HELM.R1); code.addHELMElement(cysBlock); code.addHELMConnection(con); blockerCount++; } } private void addNBlock(HELMCode code) { HELMPeptide peptide = (HELMPeptide) HelmNotationService.getInstance().getHELMElementByName("PEPTIDE1", code); HELMElement cBlock = new HELMChem(appPrefs.getString(PreferencesService.C_BLOCKER)); code.addHELMElement(cBlock); HELMConnection con = new HELMConnection(peptide, peptide.getSimpleSequence().length(), HELM.R2, cBlock, 1, HELM.R1); code.addHELMConnection(con); blockerCount++; } private void addCBlock(HELMCode code) { HELMPeptide peptide = (HELMPeptide) HelmNotationService.getInstance().getHELMElementByName("PEPTIDE1", code); HELMElement nBlock = new HELMChem(appPrefs.getString(PreferencesService.N_BLOCKER)); code.addHELMElement(nBlock); HELMConnection con = new HELMConnection(peptide, 1, HELM.R1, nBlock, 1, HELM.R1); code.addHELMConnection(con); blockerCount++; } private void adaptHELMCodeForSyncBack(Domain newDomain, HELMPeptide pep, HELMCode code, List<HELMElement> handledElemets, Map<HELMElement, Sequence> helmToSequence) { int offset = 0; HelmNotationService hs = HelmNotationService.getInstance(); List<HELMConnection> connections = hs.getConnectionsByHELMElement(code, pep); if (pep.getSimpleSequence().startsWith(newDomain.getSequence())) { offset = newDomain.getSequence().length(); String newSequence = pep.getSimpleSequence().substring(offset); pep.setSequenceRepresentation(hs.simpleSequenceToSequenceRepresentation(newSequence)); HELMPeptide newPeptide = new HELMPeptide( hs.simpleSequenceToSequenceRepresentation(newDomain.getSequence())); code.addHELMElement(newPeptide); handledElemets.add(newPeptide); helmToSequence.put(newPeptide, newDomain); for (HELMConnection con : connections) { if (con.getSource() == pep) { if (con.getSourcePosition() > offset) { con.setSourcePosition(con.getSourcePosition() - offset); } else { con.setSource(newPeptide); } } if (con.getTarget() == pep) { if (con.getTargetPosition() > offset) { con.setTargetPosition(con.getTargetPosition() - offset); } else { con.setTarget(newPeptide); } } } } } }