All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xmlcml.cml.tools.FragmentSequence Maven / Gradle / Ivy

/**
 *    Copyright 2011 Peter Murray-Rust et. al.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.xmlcml.cml.tools;

import java.util.ArrayList;
import java.util.List;

import nu.xom.Attribute;
import nu.xom.Elements;

import org.apache.log4j.Logger;
import org.xmlcml.cml.base.CMLConstants;
import org.xmlcml.cml.element.CMLArg;
import org.xmlcml.cml.element.CMLBond;
import org.xmlcml.cml.element.CMLJoin;
import org.xmlcml.cml.element.CMLLabel;
import org.xmlcml.cml.element.CMLLength;
import org.xmlcml.cml.element.CMLMolecule;
import org.xmlcml.cml.element.CMLMoleculeList;
import org.xmlcml.cml.element.CMLTorsion;
import org.xmlcml.cml.element.CMLLabel.Position;
import org.xmlcml.euclid.Util;


/**
 * tool to support fragments building. not fully developed
 * 
 * @author pmr
 * typical concise string (out of date)
  formula='f:h~r1-
  (r1~f:acryl
  [r3-(r1~f:eo~r2)range(2,5)-r1~f:et]
  ~r2)range(6,10)
  -r1:f:h
 * pseudo BNF for concise string (not finished) is:
 * concise := fragment | fragmentList
 * fragmentRepeat := '(' fragment ')' fragmentCount
 * fragmentCount := DIGIT+ |
 *         'range(' DIGIT+ ',' DIGIT+ ')' |
 *         'gaussian(' DIGIT+ ',' DIGIT+ ')'
 * fragment := '(' left? ref branch* right? ')'
 * left := '[' label ']'
 * label := 'r' DIGIT+
 * right := '[' label ']'
 * branch := '[' label concise ']'  
 * count := '*' '(' DIGIT+ | distrib ')
 * distrib := (gaussian DIGIT+ DIGIT+) | (range DIGIT+ DIGIT+) 
 * 
 * at present additional (cyclic) joins not supported
 */

/** class to support result of parse.
 * 
 * @author pm286
 *
 */
class FragmentSequence implements CMLConstants {
	@SuppressWarnings("unused")
	private static Logger LOG = Logger.getLogger(FragmentSequence.class);
    List fragmentAndBondList = null; 
    
//    private String value;

    /** process concise string.
     * @param formula string
     */
    public FragmentSequence(String formula) {
        fragmentAndBondList = 
            new ArrayList();
        if (formula == null) {
            throw new RuntimeException("null concise string");
        }
        formula = formula.trim();
        while (formula.length() > 0) {
            if (formula.charAt(0) != Fragment.LFRAGLIST) {
                throw new RuntimeException("expected '"+Fragment.LFRAGLIST+"' at: "+formula);
            }
            int idx = Util.indexOfBalancedBracket(Fragment.LFRAGLIST, formula);
            if (idx == -1) {
                throw new RuntimeException("Unblanced '"+
                    Fragment.LFRAGLIST+"..."+Fragment.RFRAGLIST+"' at: "+formula);
            }
            FragmentAndBond fragmentAndBond = new FragmentAndBond();
            this.addFragmentAndBond(fragmentAndBond);
            String fragmentS = formula.substring(1, idx);
            Fragment fragment = new Fragment(fragmentS);
            fragmentAndBond.setFragment(fragment);
            formula = formula.substring(fragmentS.length()+2);
            
            String countExpressionS = CountExpression.grabCountString(formula);
            if (formula.length() == 0) {
                break;
            }

            if (countExpressionS != null &&
                    !countExpressionS.equals(S_EMPTY)) {
                CountExpression countExpression = new CountExpression(countExpressionS);
                fragment.setCountExpression(countExpression);
                formula = formula.substring(countExpressionS.length());
            }
            
            if (formula.length() == 0) {
                break;
            }
            String joinBondS = JoinBond.grabJoinString(formula);
            if (joinBondS.equals(S_EMPTY)) {
                throw new RuntimeException("Expected bond at: "+formula);
            }
            JoinBond joinBond = new JoinBond(joinBondS);
            fragmentAndBond.setJoinBond(joinBond);
            formula = formula.substring(joinBondS.length());
        }
//        LOG.debug("FSEQ "+this.toString());
    }


    /** build up fragments.
     * 
     * @param fragmentAndBond
     */
    private void addFragmentAndBond(FragmentAndBond fragmentAndBond) {
        fragmentAndBondList.add(fragmentAndBond);
    }
    
    /** gets CMLJoin from fragments.
     * 
     * @return join
     */
    CMLMoleculeList getCMLMoleculeList() {
//        CMLJoin join = new CMLJoin();
//        join.addAttribute(
        CMLMoleculeList moleculeList = new CMLMoleculeList();
        moleculeList.addAttribute(
            new Attribute("convention", CMLJoin.FRAGMENT_CONTAINER));
        for (FragmentAndBond fragmentAndBond : fragmentAndBondList) {
            Fragment fragment = fragmentAndBond.getFragment();
            CMLMolecule molecule = fragment.getMolecule();
            Elements molecules = moleculeList.getChildCMLElements(CMLMolecule.TAG);
            // hanging bond inside repeatable molecules
            CMLMolecule previousMolecule = null;
            if (molecules.size() > 0) {
                previousMolecule = (CMLMolecule) molecules.get(molecules.size()-1);
            }
            // repeatable molecule?
            if (previousMolecule != null && 
                    // FIXME
//                previousMolecule.getCountExpression() != null &&
                molecule.getRef() == null) {
                // associated join
                Elements joins = moleculeList.getChildCMLElements(CMLJoin.TAG);
                CMLJoin previousJoin = null;
                if (joins.size() > 0) {
                    previousJoin = (CMLJoin) joins.get(joins.size()-1);
                }
                if (previousJoin != null) {
                    previousJoin.detach();
                    previousMolecule.appendChild(previousJoin);
                }
                previousMolecule.appendChild(molecule);
                // add join from after countExpression
                CMLJoin subJoin = fragmentAndBond.getCMLJoin();
                if (subJoin != null) {
                    moleculeList.appendChild(subJoin);
                }
            } else {
                // normal concatenation
                moleculeList.appendChild(molecule);
                CMLJoin subJoin = fragmentAndBond.getCMLJoin();
                if (subJoin != null) {
                    moleculeList.appendChild(subJoin);
                }
            }
        }
        return moleculeList;
    }
    
//    /** get list of fragments.
//     * 
//     * @return the list
//     */
//    private List getFragmentAndBondList() {
//        return this.fragmentAndBondList;
//    }
//
    /** debug string.
     * @return the string
     */
    public String getString() {
        StringBuffer sb = new StringBuffer();
        sb.append("");
        for (FragmentAndBond fragmentAndBond : fragmentAndBondList) {
            sb.append(fragmentAndBond.getString());
       }
        sb.append("");
       return sb.toString();
    }

    /** string.
     * @return the string
     */
    public String toString() {
        StringBuffer sb = new StringBuffer();
        for (FragmentAndBond fragmentAndBond : fragmentAndBondList) {
            sb.append(fragmentAndBond.toString());
       }
       return sb.toString();
    }

};

class FragmentAndBond implements CMLConstants {

    private Fragment fragment;
    private JoinBond joinBond;
    
    /** constructor.
     */
    public FragmentAndBond() {
    }
    
    /** set fragment at end of partial parse.
     * will trim brackets from fragmentList if countExpression set
     * @param fragment the complete fragment without trailing bond
     */
    void setFragment(Fragment fragment) {
        this.fragment = fragment;
    }
    
    /** get fragment
     * 
     * @return the fragment
     */
    Fragment getFragment() {
        return fragment;
    }
    
    /** set joinBond.
     * 
     * @param joinBond
     */
    void setJoinBond(JoinBond joinBond) {
        this.joinBond = joinBond;
    }

    /** get join from joinBond.
     * 
     * @return the join
     */
    CMLJoin getCMLJoin() {
        return (joinBond == null) ? null : joinBond.getCMLJoin();
    }
    /** debug string.
     * @return the string
     */
    public String getString() {
        StringBuffer sb = new StringBuffer();
        sb.append("");
        sb.append(fragment.getString());
        sb.append("");
        if (joinBond != null) {
            sb.append(joinBond.getString());
        }
        sb.append("");
        sb.append("");
       return sb.toString();
    }
    
    /** string.
     * @return the string
     */
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append(fragment.toString());
        if (joinBond != null) {
            sb.append(joinBond.toString());
        }
       return sb.toString();
    }

};

class Fragment implements CMLConstants {

    static char LFRAGLIST = C_LBRAK;
    static char RFRAGLIST = C_RBRAK;
    static char LLABEL = C_LCURLY;
    static char RLABEL = C_RCURLY;
    static char PARAM = C_PERCENT;
    
    private CountExpression countExpression;
    private JoinBond repeatableBond;
    private String fragmentS;
    
    private List branchList;
    private String localRefS;
    private String prefixS;

    private String leftLabel;
    private String rightLabel;
    
    Branch branch;

    private List paramList;

    /** create fragment from string.
     * 
     * @param fragmentS
     */
    public Fragment(String fragmentS) {
        init();
        this.fragmentS = fragmentS;
        parse(this.fragmentS);
    }

    private void init() {
        this.branchList = new ArrayList();
        this.paramList = new ArrayList();
        this.countExpression = null;
        this.leftLabel = S_EMPTY;
        this.rightLabel = S_EMPTY;
        this.prefixS = S_EMPTY;
        this.localRefS = S_EMPTY;
    }
    
    /** set countExpression.
     * will trim fragmentList if necessary
     * @param countExpression
     */
    void setCountExpression(CountExpression countExpression) {
        this.countExpression = countExpression;
    }
    
//    /** if fragment is repeatable, set the bond to join them.
//     * @param repeatableBond
//     */
//    private void setRepeatableBond(JoinBond repeatableBond) {
//        this.repeatableBond = repeatableBond;
//    }
    
    /** adds branch to branchList
     * @param branch to add
     */
    public void addBranch(Branch branch) {
        this.branchList.add(branch);
    }

    CMLMolecule getMolecule() {
        CMLMolecule molecule = new CMLMolecule();
        String refS = (this.prefixS.equals(S_EMPTY)) ? 
                this.localRefS : 
            this.prefixS+S_COLON+this.localRefS;
        molecule.setRef(refS);
        if (this.countExpression != null) {
            molecule.addAttribute(new Attribute("countExpression", 
                    this.countExpression.toString()));
            if (repeatableBond != null) {
                CMLJoin join = repeatableBond.getCMLJoin();
                molecule.appendChild(join);
            }
        }
        for (Param param : paramList) {
            CMLArg arg = new CMLArg();
            arg.setName(param.name);
            arg.setString(param.value);
            molecule.insertChild(arg, 0);
        }
        for (Branch branch : branchList) {
            CMLMoleculeList join = branch.getMoleculeList();
            molecule.appendChild(join);
        }
// replaced by leftLabel on molecule        
//        CMLJoin join = new CMLJoin();
        if (!this.leftLabel.equals(S_EMPTY)) {
            CMLLabel.setLabel(molecule, CMLLabel.Position.LEFT, leftLabel);
        }
        if (!this.rightLabel.equals(S_EMPTY)) {
            CMLLabel.setLabel(molecule, CMLLabel.Position.RIGHT, rightLabel);
        }
        return molecule;
    }

    /** string 
     * of form leftLabel? namespace? ref rightLabel? OR
     * rightLabel
     * @param refS
     */
    private void parse(String refS) {
        // find llabel
        localRefS = refS;
        int idx = localRefS.indexOf(LLABEL);
        if (idx != -1) {
            leftLabel = localRefS.substring(0, idx);
            localRefS = localRefS.substring(idx+1);
        }
        int lr = localRefS.length();
        if (lr == 0) {
            throw new RuntimeException("no ref given");
        }
        idx = localRefS.indexOf(S_COLON);
        if (idx != -1) {
            prefixS = localRefS.substring(0, idx);
            localRefS = localRefS.substring(idx+1);
        }
        idx = getNextPunctuation(localRefS);
        if (idx == -1) {
        } else {
            String rightS = localRefS.substring(idx);
            localRefS = localRefS.substring(0, idx);
            while (true) {
                if (rightS.length() == 0) {
                    break;
                }
                char rc = rightS.charAt(0);
                if (JoinBond.isBondChar(rc)) {
                    String joinBondS = JoinBond.grabJoinString(rightS);
                    repeatableBond = new JoinBond(joinBondS);
                    rightS = rightS.substring(joinBondS.length());
                    if (!rightS.equals(S_EMPTY)) {
                        throw new RuntimeException("Unexpected fragment after " +
                                "repeatableBond :"+rightS+S_COLON);
                    }
                } else if (rc == Branch.LBRANCH) {
                    String branchS = Branch.grabBranch(rightS);
                    Branch branch = new Branch(branchS.substring(1, branchS.length()-1));
                    branchList.add(branch);
                    rightS = rightS.substring(branchS.length());
                } else if (rc == PARAM) {
                    // %...% encloses molecule parameters
                    rightS = rightS.substring(1);
                    idx = rightS.indexOf(PARAM);
                    if (idx == -1) {
                        throw new RuntimeException("missing balancing parameter delimiter: "+PARAM);
                    }
                    String paramS = rightS.substring(0, idx);
                    rightS = rightS.substring(idx+1);
                    processParams(paramS);
                } else if (rc == RLABEL) {
                    rightS = rightS.substring(1);
                    rightLabel = rightS;
                    idx = getNextPunctuation(rightS);
                    if (idx != -1) {
                        if (JoinBond.isBondChar(rightS.charAt(idx))) {
                            rightS = rightS.substring(idx);
                            rightLabel = rightLabel.substring(0, idx);
                        } else {
                            throw new RuntimeException("Unexpected fragment after right label: "+rightS.substring(idx));
                        }
                    } else {
                        // ends with rlabel
                        break;
                    }
                } else {
                    throw new RuntimeException("Unexpected fragment in parse: "+rightS);
                }
            }
        }
    }

    private int getNextPunctuation(String s) {
        int idx = -1;
        int l = s.length();
        for (int i = 0; i < l; i++) {
            char c = s.charAt(i);
            if (JoinBond.isBondChar(c) ||
                    c == Branch.LBRANCH || 
                    c == PARAM || 
                    c == RLABEL
                    ) {
                idx = i;
                break;
            }
        }
        return idx;
    }
    
    private void processParams(String p) {
        String[] params = p.split(S_COMMA);
        for (String param : params) {
            Param pp = new Param(param);
            this.paramList.add(pp);
        }
    }
    
    /** debug string.
     * @return string
     */
    public String getString() {
        StringBuffer sb = new StringBuffer();
        sb.append("");
        sb.append("");
        if (!leftLabel.equals(S_EMPTY)) {
            sb.append(leftLabel);
        }
        sb.append("");
        sb.append("

"); if (!prefixS.equals(S_EMPTY)) { sb.append(prefixS); sb.append(S_COLON); } sb.append("

"); sb.append(""); sb.append(localRefS); sb.append(""); for (Branch branch : branchList) { sb.append(branch.getString()); } sb.append(""); if (!rightLabel.equals(S_EMPTY)) { sb.append(rightLabel); } sb.append(""); sb.append(""); if (repeatableBond != null) { sb.append(repeatableBond.getString()); } sb.append(""); sb.append(""); if (countExpression != null) { sb.append(countExpression.getString()); } sb.append(""); sb.append("
"); String s = sb.toString(); return s; } /** string. * @return string */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append(LFRAGLIST); if (!leftLabel.equals(S_EMPTY)) { sb.append(leftLabel); sb.append(LLABEL); } if (!prefixS.equals(S_EMPTY)) { sb.append(prefixS); sb.append(S_COLON); } sb.append(localRefS); for (Branch branch : branchList) { sb.append(branch.toString()); } if (!rightLabel.equals(S_EMPTY)) { sb.append(RLABEL); sb.append(rightLabel); } if (repeatableBond != null) { sb.append(repeatableBond); } sb.append(RFRAGLIST); if (countExpression != null) { sb.append(countExpression); } String s = sb.toString(); return s; } }; class JoinBond implements CMLConstants { private static Logger LOG = Logger.getLogger(JoinBond.class); static char LBOND = C_LSQUARE; static char RBOND = C_RSQUARE; /** single bond symbol. */ public final static char SINGLEBOND = C_MINUS; /** double bond symbol. */ public final static char DOUBLEBOND = C_EQUALS; /** triple bond symbol. */ public final static char TRIPLEBOND = C_HASH; CMLLength length = null; CMLTorsion torsion = null; String torsionS = null; // original value (for parsing) String lengthS = null; String order = CMLBond.SINGLE_S; String joinBondS = null; /** length keyword. */ public final static String LEN = "l"; /** torsion keyword. */ public final static String TOR = "t"; /** constructor. * * @param jBondS */ public JoinBond(String jBondS) { if (jBondS == null || jBondS.trim().length() == 0) { throw new RuntimeException("empty bond type"); } this.joinBondS = jBondS; char c = jBondS.charAt(0); if (c == SINGLEBOND) { order = CMLBond.SINGLE_S; } else if (c == DOUBLEBOND) { order = CMLBond.DOUBLE_D; } else if (c == TRIPLEBOND) { order = CMLBond.TRIPLE_T; } else { throw new RuntimeException("Bad bond type: "+c); } jBondS = jBondS.substring(1); processQualifiers(jBondS); } static String grabJoinString(String fff) { String ff = fff; String s = S_EMPTY; if (ff.length() > 0) { if (!JoinBond.isBondChar(ff.charAt(0))) { throw new RuntimeException("expected bond type at: "+ff+" in "+fff); } String f = ff.substring(1); // bond type s = ff.substring(0, 1); // bond type and qualifiers if (f.length() > 0 && f.charAt(0) == JoinBond.LBOND) { int rbr = Util.indexOfBalancedBracket(JoinBond.LBOND, f); if (rbr == -1) { throw new RuntimeException( "Unbalanced: "+JoinBond.LBOND+"..."+JoinBond.RBOND); } s += f.substring(0, rbr+1); } else { s = ff.substring(0, 1); } } return s; } /** current syntax. * len(1.4),tor(...) * tor is tor(120) or tor(evaluate(...)) * @param jBondS */ void processQualifiers(String jBondS) { if (jBondS.equals(S_EMPTY)) { } else if (jBondS.charAt(0) == LBOND) { int idx = Util.indexOfBalancedBracket(LBOND, jBondS); if (idx == -1) { throw new RuntimeException("Unbalanced "+LBOND+"..."+RBOND); } jBondS = jBondS.substring(1, jBondS.length()-1); if (jBondS.equals(S_EMPTY)) { // throw new RuntimeException("bond qualifier should not be empty"); LOG.debug("empty bond qualifier"); } lengthS = null; torsionS = null; while(jBondS.length() > 0) { if (jBondS.startsWith(LEN+C_LBRAK)) { lengthS = grabKeywordBrackets(LEN, jBondS); processLength(lengthS); jBondS = jBondS.substring(LEN.length()+lengthS.length()+2); } else if (jBondS.startsWith(TOR+C_LBRAK)) { torsionS = grabKeywordBrackets(TOR, jBondS); processTorsion(torsionS); jBondS = jBondS.substring(TOR.length()+torsionS.length()+2); } else if (jBondS.charAt(0) == C_COMMA) { jBondS = jBondS.substring(1); } else { throw new RuntimeException("must give keyworded qualifiers ("+LEN+", etc) for bond/join"); } } } } String grabKeywordBrackets(String keyword, String s) { s = s.substring(keyword.length()); int idx = Util.indexOfBalancedBracket(C_LBRAK, s); if (idx == -1) { throw new RuntimeException("Cannot find balanced bracket in: "+s); } return s.substring(1, idx); } String grabNumber(String s) { int idx = s.indexOf(S_COMMA); if (idx != -1) { s = s.substring(0, idx); } try { new Double(s); } catch (NumberFormatException e) { s = null; } return s; } void processLength(String s) { try { Double lengthD = new Double(s); if (lengthD != null) { length = new CMLLength(); length.setXMLContent(lengthD.doubleValue()); } } catch (NumberFormatException e) { throw new RuntimeException("Cannot interpret as length: "+e); } } void processTorsion(String s) { try { Double torsionD = new Double(s); if (torsionD != null) { torsion = new CMLTorsion(); torsion.setXMLContent(torsionD.doubleValue()); } } catch (NumberFormatException e) { throw new RuntimeException("Cannot interpret as torsion: "+e); } } CMLJoin getCMLJoin() { CMLJoin subJoin = new CMLJoin(); CMLTorsion torsion = this.getTorsion(); if (torsion != null) { torsion.detach(); subJoin.appendChild(torsion); } CMLLength length = this.getLength(); if (length != null) { length.detach(); subJoin.appendChild(length); } if (this.order != null) { subJoin.setOrder(this.order); } return subJoin; } CMLLength getLength() { return length; } CMLTorsion getTorsion() { return torsion; } /** get debug string. * * @return the string */ public String getString() { StringBuffer sb = new StringBuffer(); sb.append(""); sb.append(""); sb.append(getOrderSymbol(order)); sb.append(""); sb.append(""); sb.append(""); if (length != null) { sb.append(lengthS); } sb.append(""); sb.append(""); if (torsion != null) { sb.append(torsionS); } sb.append(""); sb.append(""); sb.append(""); return sb.toString(); } /** get original string. * * @return the string */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append(getOrderSymbol(order)); if (length != null || torsion != null) { sb.append(LBOND); if (length != null) { sb.append(LEN); sb.append(C_LBRAK); sb.append(lengthS); sb.append(C_RBRAK); } if (torsion != null) { sb.append(TOR); sb.append(C_LBRAK); sb.append(torsionS); sb.append(C_RBRAK); } sb.append(RBOND); } return sb.toString(); } /** translate CMLBond order into symbols. * * @param orderS CMLBond.SINGLE, etc. * @return S_MINUS, S_EQUALS, etc. */ public static String getOrderSymbol(String orderS) { String orderSymbol = S_MINUS; if (orderS == null || CMLBond.isSingle(orderS)) { } else if (CMLBond.isDouble(orderS)) { orderSymbol = S_EQUALS; } else if (CMLBond.isTriple(orderS)) { orderSymbol = S_HASH; } return orderSymbol; } /** does this character define a bond. * * @param c character * @return tru id SINGLE/DOUBLE/TRIPLE */ public static boolean isBondChar(char c) { boolean isChar = c == SINGLEBOND || c == DOUBLEBOND || c == TRIPLEBOND; return isChar; } } class Branch implements CMLConstants { static char LBRANCH = C_LSQUARE; static char RBRANCH = C_RSQUARE; String leftLabel; JoinBond joinBond; FragmentSequence fragmentSequence = null; CMLMoleculeList moleculeList; String branchS = S_EMPTY; /** parse string to create branch. * * @param brs full branch string */ public Branch(String brs) { this.branchS = brs; leftLabel = grabParentLink(branchS); branchS = branchS.substring(leftLabel.length()); String joinString = JoinBond.grabJoinString(branchS); joinBond = new JoinBond(joinString); branchS = branchS.substring(joinString.length()); fragmentSequence = new FragmentSequence(branchS); moleculeList = fragmentSequence.getCMLMoleculeList(); CMLLabel.setLabel(moleculeList, Position.PARENT, leftLabel); CMLJoin subJoin = this.getSubJoin(); moleculeList.insertChild(subJoin, 0); moleculeList.setConvention(FragmentTool.Convention.BRANCH.v); } static String grabBranch(String s) { if (s != null && s.length() > 0 && s.charAt(0) == LBRANCH) { int idx = Util.indexOfBalancedBracket(LBRANCH, s); s = s.substring(0, idx+1); } return s; } private String grabParentLink(String s) { int idx = 0; while (true) { if (idx >= s.length()) { throw new RuntimeException("expect bond after parentLInk in branch"); } if (JoinBond.isBondChar(s.charAt(idx))) { break; } idx++; } return s.substring(0, idx); } /** return new join element and add convert fragment children to molecules. * * @return the join */ CMLMoleculeList getMoleculeList() { return moleculeList; } private CMLJoin getSubJoin() { CMLJoin subJoin = new CMLJoin(); subJoin.setOrder(joinBond.order); CMLLength length = joinBond.getLength(); if (length != null) { length.detach(); subJoin.appendChild(length); } CMLTorsion torsion = joinBond.getTorsion(); if (torsion != null) { torsion.detach(); subJoin.appendChild(torsion); } return subJoin; } /** debug string. * @return value */ public String getString() { StringBuffer sb = new StringBuffer(); sb.append("
"); sb.append(""); sb.append(leftLabel); sb.append(""); sb.append(""); sb.append(joinBond.getString()); sb.append(""); sb.append(fragmentSequence.getString()); sb.append("
"); return sb.toString(); } /** to string. * @return value */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append(LBRANCH); sb.append(leftLabel); sb.append(Fragment.RLABEL); sb.append(joinBond.getString()); sb.append(fragmentSequence.getString()); sb.append(RBRANCH); return sb.toString(); } }; class CountExpression implements CMLConstants { /** left bracket for count. */ static char LCOUNTBRAK = C_LBRAK; /** right bracket for count. */ static char RCOUNTBRAK = C_RBRAK; /** range. */ public static String RANGE = "range"; /** gaussian. */ public static String GAUSSIAN = "gaussian"; String countExpressionS; /** constructor. * * @param s raw string */ public CountExpression(String s) { countExpressionS = s; } /** return raw string. * * @return raw string */ public String getString() { StringBuffer sb = new StringBuffer(); sb.append(""); sb.append(countExpressionS); sb.append(""); return sb.toString(); } /** grabs countExpression if it exists. * * @param formula * @return empty string if none */ static String grabCountString(String formula) { String s = S_EMPTY; int ll = 0; if (formula.length() == 0) { } else if (formula.startsWith(S_STAR+LCOUNTBRAK)) { ll = 1; } else if (formula.startsWith(RANGE+LCOUNTBRAK)) { ll = RANGE.length(); } else if (formula.startsWith(GAUSSIAN+LCOUNTBRAK)) { ll = GAUSSIAN.length(); } else { } if (ll != 0) { int rbr = Util.indexOfBalancedBracket(LCOUNTBRAK, formula.substring(ll)); if (rbr == -1) { throw new RuntimeException("Cannot find balanced bracket:"+formula); } s = formula.substring(0, rbr+ll+1); } return s; } /** to string. * @return value */ public String toString() { StringBuffer sb = new StringBuffer(); sb.append(countExpressionS); return sb.toString(); } }; class Param implements CMLConstants { String name; String value; /** parse name value pair. * of form a=b * @param s string to parse */ public Param(String s) { String[] pp = s.split(S_EQUALS); if (pp.length != 2) { throw new RuntimeException("Param1 must be of type a=b; "+s); } name = pp[0]; value = pp[1]; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy