/* $Revision$ $Author$ $Date$
*
* Copyright (C) 2004-2007 The Chemistry Development Kit (CDK) project
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
* (or see http://www.gnu.org/copyleft/lesser.html)
*/
package org.openscience.cdk.smiles.smarts.parser.visitor;
import java.util.ArrayList;
import java.util.List;
import org.openscience.cdk.CDKConstants;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.interfaces.IBond;
import org.openscience.cdk.isomorphism.matchers.IQueryAtom;
import org.openscience.cdk.isomorphism.matchers.IQueryAtomContainer;
import org.openscience.cdk.isomorphism.matchers.IQueryBond;
import org.openscience.cdk.isomorphism.matchers.QueryAtomContainer;
import org.openscience.cdk.isomorphism.matchers.smarts.AliphaticAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.AliphaticSymbolAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.AnyAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.AnyOrderQueryBond;
import org.openscience.cdk.isomorphism.matchers.smarts.AromaticAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.AromaticOrSingleQueryBond;
import org.openscience.cdk.isomorphism.matchers.smarts.AromaticQueryBond;
import org.openscience.cdk.isomorphism.matchers.smarts.AromaticSymbolAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.AtomicNumberAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.ChiralityAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.ExplicitConnectionAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.FormalChargeAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.HybridizationNumberAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.HydrogenAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.ImplicitHCountAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.LogicalOperatorAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.LogicalOperatorBond;
import org.openscience.cdk.isomorphism.matchers.smarts.MassAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.NonCHHeavyAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.OrderQueryBond;
import org.openscience.cdk.isomorphism.matchers.smarts.PeriodicGroupNumberAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.RecursiveSmartsAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.RingBond;
import org.openscience.cdk.isomorphism.matchers.smarts.RingIdentifierAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.RingMembershipAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.SMARTSAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.SMARTSBond;
import org.openscience.cdk.isomorphism.matchers.smarts.SmallestRingAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.StereoBond;
import org.openscience.cdk.isomorphism.matchers.smarts.TotalConnectionAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.TotalHCountAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.TotalRingConnectionAtom;
import org.openscience.cdk.isomorphism.matchers.smarts.TotalValencyAtom;
import org.openscience.cdk.smiles.smarts.parser.ASTAliphatic;
import org.openscience.cdk.smiles.smarts.parser.ASTAnyAtom;
import org.openscience.cdk.smiles.smarts.parser.ASTAromatic;
import org.openscience.cdk.smiles.smarts.parser.ASTAtom;
import org.openscience.cdk.smiles.smarts.parser.ASTAtomicMass;
import org.openscience.cdk.smiles.smarts.parser.ASTAtomicNumber;
import org.openscience.cdk.smiles.smarts.parser.ASTCharge;
import org.openscience.cdk.smiles.smarts.parser.ASTChirality;
import org.openscience.cdk.smiles.smarts.parser.ASTElement;
import org.openscience.cdk.smiles.smarts.parser.ASTExplicitAtom;
import org.openscience.cdk.smiles.smarts.parser.ASTExplicitConnectivity;
import org.openscience.cdk.smiles.smarts.parser.ASTExplicitHighAndBond;
import org.openscience.cdk.smiles.smarts.parser.ASTExplicitHighAndExpression;
import org.openscience.cdk.smiles.smarts.parser.ASTGroup;
import org.openscience.cdk.smiles.smarts.parser.ASTHybrdizationNumber;
import org.openscience.cdk.smiles.smarts.parser.ASTImplicitHCount;
import org.openscience.cdk.smiles.smarts.parser.ASTImplicitHighAndBond;
import org.openscience.cdk.smiles.smarts.parser.ASTImplicitHighAndExpression;
import org.openscience.cdk.smiles.smarts.parser.ASTLowAndBond;
import org.openscience.cdk.smiles.smarts.parser.ASTLowAndExpression;
import org.openscience.cdk.smiles.smarts.parser.ASTNonCHHeavyAtom;
import org.openscience.cdk.smiles.smarts.parser.ASTNotBond;
import org.openscience.cdk.smiles.smarts.parser.ASTNotExpression;
import org.openscience.cdk.smiles.smarts.parser.ASTOrBond;
import org.openscience.cdk.smiles.smarts.parser.ASTOrExpression;
import org.openscience.cdk.smiles.smarts.parser.ASTPeriodicGroupNumber;
import org.openscience.cdk.smiles.smarts.parser.ASTReaction;
import org.openscience.cdk.smiles.smarts.parser.ASTRecursiveSmartsExpression;
import org.openscience.cdk.smiles.smarts.parser.ASTRingConnectivity;
import org.openscience.cdk.smiles.smarts.parser.ASTRingIdentifier;
import org.openscience.cdk.smiles.smarts.parser.ASTRingMembership;
import org.openscience.cdk.smiles.smarts.parser.ASTSimpleBond;
import org.openscience.cdk.smiles.smarts.parser.ASTSmallestRingSize;
import org.openscience.cdk.smiles.smarts.parser.ASTSmarts;
import org.openscience.cdk.smiles.smarts.parser.ASTStart;
import org.openscience.cdk.smiles.smarts.parser.ASTTotalConnectivity;
import org.openscience.cdk.smiles.smarts.parser.ASTTotalHCount;
import org.openscience.cdk.smiles.smarts.parser.ASTValence;
import org.openscience.cdk.smiles.smarts.parser.Node;
import org.openscience.cdk.smiles.smarts.parser.SMARTSParserConstants;
import org.openscience.cdk.smiles.smarts.parser.SMARTSParserVisitor;
import org.openscience.cdk.smiles.smarts.parser.SimpleNode;
import org.openscience.cdk.tools.ILoggingTool;
import org.openscience.cdk.tools.LoggingToolFactory;
/**
* An AST tree visitor. It builds an instance of <code>QueryAtomContainer</code>
* from the AST tree.
*
* To use this visitor:
* <pre>
* SMARTSParser parser = new SMARTSParser(new java.io.StringReader("C*C"));
* ASTStart ast = parser.start();
* SmartsQueryVisitor visitor = new SmartsQueryVisitor();
* QueryAtomContainer query = visitor.visit(ast, null);
* </pre>
*
* @author Dazhi Jiao
* @cdk.created 2007-04-24
* @cdk.module smarts
* @cdk.githash
* @cdk.keyword SMARTS AST
*/
public class SmartsQueryVisitor implements SMARTSParserVisitor {
// current atoms with a ring identifier
private RingIdentifierAtom[] ringAtoms;
// current atoms in recursive smarts with a ring identifier
private RingIdentifierAtom[] recursiveRingAtoms;
// query
private IQueryAtomContainer query;
// Whether is parsing a recursive smarts
private boolean isParsingRS;
// Recursive smarts query
private IQueryAtomContainer rsQuery;
public Object visit(ASTRingIdentifier node, Object data) {
IQueryAtom atom = (IQueryAtom)data;
RingIdentifierAtom ringIdAtom = new RingIdentifierAtom();
ringIdAtom.setAtom(atom);
IQueryBond bond;
if (node.jjtGetNumChildren() == 0) { // implicit bond
bond = null;
} else {
bond = (IQueryBond)node.jjtGetChild(0).jjtAccept(this, data);
}
ringIdAtom.setRingBond(bond);
return ringIdAtom;
}
public Object visit(ASTAtom node, Object data) {
IQueryAtom atom = (IQueryAtom)node.jjtGetChild(0).jjtAccept(this, data);
for (int i = 1; i < node.jjtGetNumChildren(); i++) { // if there are ring identifiers
ASTRingIdentifier ringIdentifier = (ASTRingIdentifier)node.jjtGetChild(i);
RingIdentifierAtom ringIdAtom = (RingIdentifierAtom)ringIdentifier.jjtAccept(this, atom);
// if there is already a RingIdentifierAtom, create a bond between
// them and add the bond to the query
int ringId = ringIdentifier.getRingId();
if (isParsingRS) {
if (recursiveRingAtoms[ringId] == null) {
recursiveRingAtoms[ringId] = ringIdAtom;
} else {
IQueryBond ringBond;
// first check if the two bonds ma
if (recursiveRingAtoms[ringId].getRingBond() == null) {
if (ringIdAtom.getRingBond() == null) {
if (atom instanceof AromaticSymbolAtom &&
recursiveRingAtoms[ringId].getAtom() instanceof AromaticSymbolAtom) {
ringBond = new AromaticQueryBond();
} else {
ringBond = new RingBond();
}
} else {
ringBond = ringIdAtom.getRingBond();
}
} else {
// Here I assume the bond are always same. This should be checked by the parser already
ringBond = recursiveRingAtoms[ringId].getRingBond();
}
((IBond)ringBond).setAtoms(new IAtom[] { recursiveRingAtoms[ringId].getAtom(), atom });
rsQuery.addBond((IBond)ringBond);
}
// update the recursiveRingAtom reference
recursiveRingAtoms[ringId] = ringIdAtom;
} else {
if (ringAtoms[ringId] == null) {
ringAtoms[ringId] = ringIdAtom;
} else {
IQueryBond ringBond;
// first check if the two bonds ma
if (ringAtoms[ringId].getRingBond() == null) {
if (ringIdAtom.getRingBond() == null) {
if (atom instanceof AromaticSymbolAtom &&
ringAtoms[ringId].getAtom() instanceof AromaticSymbolAtom) {
ringBond = new AromaticQueryBond();
} else {
ringBond = new RingBond();
}
} else {
ringBond = ringIdAtom.getRingBond();
}
} else {
// Here I assume the bond are always same. This should be checked by the parser already
ringBond = ringAtoms[ringId].getRingBond();
}
((IBond)ringBond).setAtoms(new IAtom[] { ringAtoms[ringId].getAtom(), atom });
query.addBond((IBond)ringBond);
}
// update the ringAtom reference
ringAtoms[ringId] = ringIdAtom;
}
}
return atom;
}
private final static ILoggingTool logger =
LoggingToolFactory.createLoggingTool(
SmartsQueryVisitor.class);
/**
* Creates a new instance
*/
public SmartsQueryVisitor() {
super();
}
public Object visit(SimpleNode node, Object data) {
return null;
}
public Object visit(ASTStart node, Object data) {
return node.jjtGetChild(0).jjtAccept(this, data);
}
// TODO: No QueryReaction API
public Object visit(ASTReaction node, Object data) {
return node.jjtGetChild(0).jjtAccept(this, data);
}
// TODO: No SmartsGroup API
public Object visit(ASTGroup node, Object data) {
List<IAtomContainer> atomContainers = new ArrayList<IAtomContainer>();
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
ringAtoms = new RingIdentifierAtom[10];
query = new QueryAtomContainer();
node.jjtGetChild(i).jjtAccept(this, null);
atomContainers.add(query);
}
logger.info("Only return the first smarts. Group not supported.");
return atomContainers.get(0);
}
public Object visit(ASTSmarts node, Object data) {
SMARTSAtom atom = null;
SMARTSBond bond = null;
ASTAtom first = (ASTAtom)node.jjtGetChild(0);
atom = (SMARTSAtom)first.jjtAccept(this, null);
if (data != null) { // this is a sub smarts
bond = (SMARTSBond)((Object[])data)[1];
if (bond == null) { // since no bond was specified it could be aromatic or single
bond = new AromaticOrSingleQueryBond();
bond.setAtoms(new IAtom[] {atom, (SMARTSAtom)((Object[])data)[0]});
} else {
bond.setAtoms(new IAtom[] {(SMARTSAtom)((Object[])data)[0], atom});
}
if (isParsingRS) rsQuery.addBond(bond);
else query.addBond(bond);
bond = null;
}
if (isParsingRS) rsQuery.addAtom(atom);
else query.addAtom(atom);
for (int i = 1; i < node.jjtGetNumChildren(); i++) {
Node child = node.jjtGetChild(i);
if (child instanceof ASTLowAndBond) {
bond = (SMARTSBond) child.jjtAccept(this, data);
} else if (child instanceof ASTAtom) {
SMARTSAtom newAtom = (SMARTSAtom)child.jjtAccept(this, null);
if (bond == null) { // since no bond was specified it could be aromatic or single
bond = new AromaticOrSingleQueryBond();
}
bond.setAtoms(new IAtom[] {atom, newAtom});
if (isParsingRS) {
rsQuery.addBond(bond);
rsQuery.addAtom(newAtom);
} else {
query.addBond(bond);
query.addAtom(newAtom);
}
atom = newAtom;
bond = null;
} else if (child instanceof ASTSmarts) { // another smarts
child.jjtAccept(this, new Object[] {atom, bond});
bond = null;
}
}
return isParsingRS ? rsQuery: query;
}
public Object visit(ASTNotBond node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.getType() == SMARTSParserConstants.DEFAULT) {
return left;
}
LogicalOperatorBond bond = new LogicalOperatorBond();
bond.setOperator("not");
bond.setLeft((IQueryBond) left);
return bond;
}
public Object visit(ASTImplicitHighAndBond node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 1) {
return left;
}
LogicalOperatorBond bond = new LogicalOperatorBond();
bond.setOperator("and");
bond.setLeft((IQueryBond) left);
IQueryBond right = (IQueryBond) node.jjtGetChild(1).jjtAccept(this,
data);
bond.setRight(right);
return bond;
}
public Object visit(ASTLowAndBond node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 1) {
return left;
}
LogicalOperatorBond bond = new LogicalOperatorBond();
bond.setOperator("and");
bond.setLeft((IQueryBond) left);
IQueryBond right = (IQueryBond) node.jjtGetChild(1).jjtAccept(this,
data);
bond.setRight(right);
return bond;
}
public Object visit(ASTOrBond node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 1) {
return left;
}
LogicalOperatorBond bond = new LogicalOperatorBond();
bond.setOperator("or");
bond.setLeft((IQueryBond) left);
IQueryBond right = (IQueryBond) node.jjtGetChild(1).jjtAccept(this,
data);
bond.setRight(right);
return bond;
}
public Object visit(ASTExplicitHighAndBond node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 1) {
return left;
}
LogicalOperatorBond bond = new LogicalOperatorBond();
bond.setOperator("and");
bond.setLeft((IQueryBond) left);
IQueryBond right = (IQueryBond) node.jjtGetChild(1).jjtAccept(this,
data);
bond.setRight(right);
return bond;
}
public Object visit(ASTSimpleBond node, Object data) {
SMARTSBond bond = null;
switch (node.getBondType()) {
case SMARTSParserConstants.S_BOND:
bond = new OrderQueryBond(IBond.Order.SINGLE);
break;
case SMARTSParserConstants.D_BOND:
bond = new OrderQueryBond(IBond.Order.DOUBLE);
break;
case SMARTSParserConstants.T_BOND:
bond = new OrderQueryBond(IBond.Order.TRIPLE);
break;
case SMARTSParserConstants.ANY_BOND:
bond = new AnyOrderQueryBond();
break;
case SMARTSParserConstants.AR_BOND:
bond = new AromaticQueryBond();
break;
case SMARTSParserConstants.R_BOND:
bond = new RingBond();
break;
case SMARTSParserConstants.UP_S_BOND:
bond = new StereoBond();
bond.setOrder(IBond.Order.SINGLE);
bond.setStereo(IBond.Stereo.UP);
break;
case SMARTSParserConstants.DN_S_BOND:
bond = new StereoBond();
bond.setOrder(IBond.Order.SINGLE);
bond.setStereo(IBond.Stereo.DOWN);
break;
case SMARTSParserConstants.UP_OR_UNSPECIFIED_S_BOND:
LogicalOperatorBond logical = new LogicalOperatorBond();
logical.setOperator("or");
StereoBond bond1 = new StereoBond();
bond1.setOrder(IBond.Order.SINGLE);
bond1.setStereo(IBond.Stereo.UP);
logical.setLeft(bond1);
StereoBond bond2 = new StereoBond();
bond2.setOrder(IBond.Order.SINGLE);
bond2.setStereo((IBond.Stereo)CDKConstants.UNSET);
logical.setRight(bond2);
bond = logical;
break;
case SMARTSParserConstants.DN_OR_UNSPECIFIED_S_BOND:
logical = new LogicalOperatorBond();
logical.setOperator("or");
bond1 = new StereoBond();
bond1.setOrder(IBond.Order.SINGLE);
bond1.setStereo(IBond.Stereo.DOWN);
logical.setLeft(bond1);
bond2 = new StereoBond();
bond2.setOrder(IBond.Order.SINGLE);
bond2.setStereo((IBond.Stereo)CDKConstants.UNSET);
logical.setRight(bond2);
bond = logical;
break;
default:
logger.error("Un parsed bond: " + node.toString());
break;
}
return bond;
}
public Object visit(ASTRecursiveSmartsExpression node, Object data) {
rsQuery = new QueryAtomContainer();
recursiveRingAtoms = new RingIdentifierAtom[10];
isParsingRS = true;
node.jjtGetChild(0).jjtAccept(this, null);
isParsingRS = false;
return new RecursiveSmartsAtom(rsQuery);
}
public ASTStart getRoot(Node node) {
if (node instanceof ASTStart) {
return (ASTStart) node;
}
return getRoot(node.jjtGetParent());
}
public Object visit(ASTElement node, Object data) {
String symbol = node.getSymbol();
SMARTSAtom atom;
if ("o".equals(symbol) || "n".equals(symbol) || "c".equals(symbol)
|| "s".equals(symbol) || "p".equals(symbol) || "as".equals(symbol)
|| "se".equals(symbol)) {
String atomSymbol = symbol.substring(0,1).toUpperCase() + symbol.substring(1);
atom = new AromaticSymbolAtom(atomSymbol);
} else {
atom = new AliphaticSymbolAtom(symbol);
}
return atom;
}
public Object visit(ASTTotalHCount node, Object data) {
return new TotalHCountAtom(node.getCount());
}
public Object visit(ASTImplicitHCount node, Object data) {
return new ImplicitHCountAtom(node.getCount());
}
public Object visit(ASTExplicitConnectivity node, Object data) {
return new ExplicitConnectionAtom(node.getNumOfConnection());
}
public Object visit(ASTAtomicNumber node, Object data) {
return new AtomicNumberAtom(node.getNumber());
}
public Object visit(ASTHybrdizationNumber node, Object data) {
return new HybridizationNumberAtom(node.getHybridizationNumber());
}
public Object visit(ASTCharge node, Object data) {
if (node.isPositive()) {
return new FormalChargeAtom(node.getCharge());
} else {
return new FormalChargeAtom(0 - node.getCharge());
}
}
public Object visit(ASTRingConnectivity node, Object data) {
return new TotalRingConnectionAtom(node.getNumOfConnection());
}
public Object visit(ASTPeriodicGroupNumber node, Object data) {
return new PeriodicGroupNumberAtom(node.getGroupNumber());
}
public Object visit(ASTTotalConnectivity node, Object data) {
return new TotalConnectionAtom(node.getNumOfConnection());
}
public Object visit(ASTValence node, Object data) {
return new TotalValencyAtom(node.getOrder());
}
public Object visit(ASTRingMembership node, Object data) {
return new RingMembershipAtom(node.getNumOfMembership());
}
public Object visit(ASTSmallestRingSize node, Object data) {
return new SmallestRingAtom(node.getSize());
}
public Object visit(ASTAliphatic node, Object data) {
return new AliphaticAtom();
}
public Object visit(ASTNonCHHeavyAtom node, Object data) {
return new NonCHHeavyAtom();
}
public Object visit(ASTAromatic node, Object data) {
return new AromaticAtom();
}
public Object visit(ASTAnyAtom node, Object data) {
return new AnyAtom();
}
public Object visit(ASTAtomicMass node, Object data) {
return new MassAtom(node.getMass());
}
public Object visit(ASTChirality node, Object data) {
ChiralityAtom atom = new ChiralityAtom();
atom.setDegree(node.getDegree());
atom.setClockwise(node.isClockwise());
atom.setUnspecified(node.isUnspecified());
return atom;
}
public Object visit(ASTLowAndExpression node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 1) {
return left;
}
LogicalOperatorAtom atom = new LogicalOperatorAtom();
atom.setOperator("and");
atom.setLeft((IQueryAtom) left);
IQueryAtom right = (IQueryAtom) node.jjtGetChild(1).jjtAccept(this,
data);
atom.setRight(right);
return atom;
}
public Object visit(ASTOrExpression node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 1) {
return left;
}
LogicalOperatorAtom atom = new LogicalOperatorAtom();
atom.setOperator("or");
atom.setLeft((IQueryAtom) left);
IQueryAtom right = (IQueryAtom) node.jjtGetChild(1).jjtAccept(this,
data);
atom.setRight(right);
return atom;
}
public Object visit(ASTNotExpression node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.getType() == SMARTSParserConstants.DEFAULT) {
return left;
}
LogicalOperatorAtom atom = new LogicalOperatorAtom();
atom.setOperator("not");
atom.setLeft((IQueryAtom) left);
return atom;
}
public Object visit(ASTExplicitHighAndExpression node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 1) {
return left;
}
LogicalOperatorAtom atom = new LogicalOperatorAtom();
atom.setOperator("and");
atom.setLeft((IQueryAtom) left);
IQueryAtom right = (IQueryAtom) node.jjtGetChild(1).jjtAccept(this,
data);
atom.setRight(right);
return atom;
}
public Object visit(ASTImplicitHighAndExpression node, Object data) {
Object left = node.jjtGetChild(0).jjtAccept(this, data);
if (node.jjtGetNumChildren() == 1) {
return left;
}
LogicalOperatorAtom atom = new LogicalOperatorAtom();
atom.setOperator("and");
atom.setLeft((IQueryAtom) left);
IQueryAtom right = (IQueryAtom) node.jjtGetChild(1).jjtAccept(this,
data);
atom.setRight(right);
return atom;
}
public Object visit(ASTExplicitAtom node, Object data) {
IQueryAtom atom = null;
String symbol = node.getSymbol();
if ("*".equals(symbol)) {
atom = new AnyAtom();
} else if ("A".equals(symbol)) {
atom = new AliphaticAtom();
} else if ("a".equals(symbol)) {
atom = new AromaticAtom();
} else if ("o".equals(symbol) || "n".equals(symbol)
|| "c".equals(symbol) || "s".equals(symbol)
|| "p".equals(symbol) || "as".equals(symbol)
|| "se".equals(symbol)) {
String atomSymbol = symbol.substring(0,1).toUpperCase() + symbol.substring(1);
atom = new AromaticSymbolAtom(atomSymbol);
} else if ("H".equals(symbol)) {
atom = new HydrogenAtom();
atom.setSymbol(symbol.toUpperCase());
atom.setMassNumber(1);
} else if ("D".equals(symbol)) {
atom = new HydrogenAtom();
atom.setSymbol(symbol.toUpperCase());
atom.setMassNumber(2);
} else if ("T".equals(symbol)) {
atom = new HydrogenAtom();
atom.setSymbol(symbol.toUpperCase());
atom.setMassNumber(3);
} else {
atom = new AliphaticSymbolAtom(symbol);
}
return atom;
}
}