(function(Clazz
,Clazz_getClassName
,Clazz_newLongArray
,Clazz_doubleToByte
,Clazz_doubleToInt
,Clazz_doubleToLong
,Clazz_declarePackage
,Clazz_instanceOf
,Clazz_load
,Clazz_instantialize
,Clazz_decorateAsClass
,Clazz_floatToInt
,Clazz_floatToLong
,Clazz_makeConstructor
,Clazz_defineEnumConstant
,Clazz_exceptionOf
,Clazz_newIntArray
,Clazz_newFloatArray
,Clazz_declareType
,Clazz_prepareFields
,Clazz_superConstructor
,Clazz_newByteArray
,Clazz_declareInterface
,Clazz_newShortArray
,Clazz_innerTypeInstance
,Clazz_isClassDefined
,Clazz_prepareCallback
,Clazz_newArray
,Clazz_castNullAs
,Clazz_floatToShort
,Clazz_superCall
,Clazz_decorateAsType
,Clazz_newBooleanArray
,Clazz_newCharArray
,Clazz_implementOf
,Clazz_newDoubleArray
,Clazz_overrideConstructor
,Clazz_clone
,Clazz_doubleToShort
,Clazz_getInheritedLevel
,Clazz_getParamsType
,Clazz_isAF
,Clazz_isAB
,Clazz_isAI
,Clazz_isAS
,Clazz_isASS
,Clazz_isAP
,Clazz_isAFloat
,Clazz_isAII
,Clazz_isAFF
,Clazz_isAFFF
,Clazz_tryToSearchAndExecute
,Clazz_getStackTrace
,Clazz_inheritArgs
,Clazz_alert
,Clazz_defineMethod
,Clazz_overrideMethod
,Clazz_declareAnonymous
//,Clazz_checkPrivateMethod
,Clazz_cloneFinals
){
var $t$;
//var c$;
Clazz_declarePackage("JS");
Clazz_load(["JU.BS", "$.V3"], "JS.VTemp", null, function(){
var c$ = Clazz_decorateAsClass(function(){
this.vTemp = null;
this.vA = null;
this.vB = null;
this.vTemp1 = null;
this.vTemp2 = null;
this.vNorm2 = null;
this.vNorm3 = null;
this.vNorm4 = null;
this.bsTemp = null;
Clazz_instantialize(this, arguments);}, JS, "VTemp", null);
Clazz_prepareFields (c$, function(){
this.vTemp =  new JU.V3();
this.vA =  new JU.V3();
this.vB =  new JU.V3();
this.vTemp1 =  new JU.V3();
this.vTemp2 =  new JU.V3();
this.vNorm2 =  new JU.V3();
this.vNorm3 =  new JU.V3();
this.vNorm4 =  new JU.V3();
this.bsTemp =  new JU.BS();
});
});
;//5.0.1-v7 Thu Feb 05 13:38:23 CST 2026
Clazz_declarePackage("J.api");
Clazz_declareInterface(J.api, "SmilesMatcherInterface");
;//5.0.1-v7 Thu Feb 05 13:38:23 CST 2026
Clazz_declarePackage("JS");
Clazz_load(["J.api.SmilesMatcherInterface"], "JS.SmilesMatcher", ["JU.AU", "$.BS", "$.PT", "JS.InvalidSmilesException", "$.SmilesAtom", "$.SmilesBond", "$.SmilesGenerator", "$.SmilesParser", "$.SmilesSearch", "JU.BSUtil", "$.Elements", "$.Logger"], function(){
var c$ = Clazz_decorateAsClass(function(){
this.okMF = true;
Clazz_instantialize(this, arguments);}, JS, "SmilesMatcher", null, J.api.SmilesMatcherInterface);
Clazz_overrideMethod(c$, "getLastException", 
function(){
return (this.okMF == true ? JS.InvalidSmilesException.getLastError() : "MF_FAILED");
});
Clazz_overrideMethod(c$, "getMolecularFormula", 
function(pattern, isSmarts, isEmpirical){
this.clearExceptions();
var search = JS.SmilesParser.newSearch("/nostereo/" + pattern.toString(), isSmarts, true);
search.createTopoMap(null);
search.nodes = search.target.nodes;
return search.getMolecularFormula(!isSmarts, null, isEmpirical);
}, "~O,~B,~B");
Clazz_defineMethod(c$, "clearExceptions", 
function(){
JS.InvalidSmilesException.clear();
});
Clazz_overrideMethod(c$, "getSmiles", 
function(atoms, ac, bsSelected, bioComment, flags){
this.clearExceptions();
return ( new JS.SmilesGenerator()).getSmiles(this, atoms, ac, bsSelected, bioComment, flags);
}, "~A,~N,JU.BS,~S,~N");
Clazz_overrideMethod(c$, "areEqual", 
function(smiles1, smiles2){
this.clearExceptions();
if ((smiles1 == null) != (smiles2 == null)) return 0;
if (smiles1 == null) return 1;
var isWild = false;
if ((typeof(smiles1)=='string') && (typeof(smiles2)=='string')) {
isWild = ((smiles1).indexOf("*") >= 0);
if (!isWild && smiles1.equals(smiles2)) return 1;
}var flags = (isWild ? 2 : 1) | 8;
var result = this.matchPriv(smiles1, null, 0, null, null, false, flags, 2, this.newSearch(smiles2));
return (result == null ? -1 : result.length);
}, "~O,~O");
Clazz_defineMethod(c$, "areEqualTest", 
function(smiles, search){
search.set();
var ret = this.matchPriv(smiles, null, 0, null, null, false, 9, 2, search);
return (ret != null && ret.length == 1);
}, "~S,JS.SmilesSearch");
Clazz_overrideMethod(c$, "find", 
function(pattern, target, flags){
this.clearExceptions();
if ((typeof(target)=='string')) target = JS.SmilesParser.cleanPattern(target);
if ((typeof(pattern)=='string')) pattern = JS.SmilesParser.cleanPattern(pattern);
var search = this.newSearch(target);
var array = this.matchPriv(pattern, null, 0, null, null, false, flags, 3, search);
for (var i = array.length; --i >= 0; ) {
var a = array[i];
for (var j = a.length; --j >= 0; ) a[j] = (search.target.nodes[a[j]]).mapIndex;

}
return array;
}, "~O,~O,~N");
Clazz_overrideMethod(c$, "getAtoms", 
function(target){
this.clearExceptions();
var search = this.newSearch(target);
search.createTopoMap( new JU.BS());
return search.target.nodes;
}, "~O");
Clazz_defineMethod(c$, "newSearch", 
function(s){
return (s == null ? null : Clazz_instanceOf(s,"JS.SmilesSearch") ? s : JS.SmilesParser.newSearch(JS.SmilesParser.cleanPattern(s.toString()), false, true));
}, "~O");
Clazz_overrideMethod(c$, "getRelationship", 
function(smiles1, smiles2){
if (smiles1 == null || smiles2 == null || smiles1.length == 0 || smiles2.length == 0) return "";
var mf1 = this.getMolecularFormula(smiles1, false, false);
var mf2 = this.getMolecularFormula(smiles2, false, false);
if (!mf1.equals(mf2)) return "none";
var check;
var n1 = JU.PT.countChar(JU.PT.rep(smiles1, "@@", "@"), '@');
var n2 = JU.PT.countChar(JU.PT.rep(smiles2, "@@", "@"), '@');
check = (n1 == n2 && this.areEqual(smiles2, smiles1) > 0);
if (!check) {
var s = smiles1 + smiles2;
if (s.indexOf("/") >= 0 || s.indexOf("\\") >= 0 || s.indexOf("@") >= 0) {
if (n1 == n2 && n1 > 0 && s.indexOf("@SP") < 0) {
check = (this.areEqual("/invertstereo/" + smiles2, smiles1) > 0);
if (check) return "enantiomers";
}check = (this.areEqual("/nostereo/" + smiles2, smiles1) > 0);
if (check) return (n1 == n2 ? "diastereomers" : "ambiguous stereochemistry!");
}return "constitutional isomers";
}return "identical";
}, "~S,~S");
Clazz_overrideMethod(c$, "reverseChirality", 
function(smiles){
smiles = JU.PT.rep(smiles, "@@", "!@");
smiles = JU.PT.rep(smiles, "@", "@@");
smiles = JU.PT.rep(smiles, "!@@", "@");
return smiles;
}, "~S");
Clazz_overrideMethod(c$, "getSubstructureSet", 
function(pattern, target, ac, bsSelected, flags){
var atoms = (Clazz_instanceOf(target,"JS.SmilesSearch") ? null : target);
return this.matchPriv(pattern, atoms, ac, bsSelected, null, true, flags | ((typeof(pattern)=='string') ? JS.SmilesParser.getFlags(pattern.toString()) : 0), 1, (atoms == null ? target : null));
}, "~O,~O,~N,JU.BS,~N");
Clazz_overrideMethod(c$, "getMMFF94AtomTypes", 
function(smarts, atoms, ac, bsSelected, ret, vRings){
this.clearExceptions();
var sp =  new JS.SmilesParser(true, true);
var search = null;
var flags = (770);
search = sp.parse("");
search.exitFirstMatch = false;
search.target.setAtoms(atoms, Math.abs(ac), bsSelected);
search.flags = flags;
search.getRingData(vRings, true, true);
search.asVector = false;
search.subSearches =  new Array(1);
search.getSelections();
var bsDone =  new JU.BS();
for (var i = 0; i < smarts.length; i++) {
if (smarts[i] == null || smarts[i].length == 0 || smarts[i].startsWith("#")) {
ret.addLast(null);
continue;
}search.clear();
search.subSearches[0] = sp.getSubsearch(search, JS.SmilesParser.cleanPattern(smarts[i]), flags);
var bs = JU.BSUtil.copy(search.search());
ret.addLast(bs);
bsDone.or(bs);
if (bsDone.cardinality() == ac) return;
}
}, "~A,~A,~N,JU.BS,JU.Lst,~A");
Clazz_overrideMethod(c$, "getSubstructureSetArray", 
function(pattern, atoms, ac, bsSelected, bsAromatic, flags){
return this.matchPriv(pattern, atoms, ac, bsSelected, bsAromatic, true, flags, 2, null);
}, "~O,~A,~N,JU.BS,JU.BS,~N");
Clazz_defineMethod(c$, "getAtropisomerKeys", 
function(pattern, atoms, ac, bsSelected, bsAromatic, flags){
return this.matchPriv(pattern, atoms, ac, bsSelected, bsAromatic, false, flags, 4, null);
}, "~S,~A,~N,JU.BS,JU.BS,~N");
Clazz_overrideMethod(c$, "polyhedronToSmiles", 
function(center, faces, atomCount, points, flags, details){
var atoms =  new Array(atomCount);
for (var i = 0; i < atomCount; i++) {
atoms[i] =  new JS.SmilesAtom();
var pt = (points == null ? null : points[i]);
if (Clazz_instanceOf(pt,"JU.Node")) {
atoms[i].elementNumber = (pt).getElementNumber();
atoms[i].bioAtomName = (pt).getAtomName();
atoms[i].atomNumber = (pt).getAtomNumber();
atoms[i].setT(pt);
} else {
atoms[i].elementNumber = (Clazz_instanceOf(pt,"JU.Point3fi") ? (pt).sD : -2);
if (pt != null) atoms[i].setT(pt);
}atoms[i].index = i;
}
var nBonds = 0;
for (var i = faces.length; --i >= 0; ) {
var face = faces[i];
var n = face.length;
var iatom;
var iatom2;
for (var j = n; --j >= 0; ) {
if ((iatom = face[j]) >= atomCount || (iatom2 = face[(j + 1) % n]) >= atomCount) continue;
if (atoms[iatom].getBondTo(atoms[iatom2]) == null) {
var b =  new JS.SmilesBond(atoms[iatom], atoms[iatom2], 1, false);
b.index = nBonds++;
}}
}
for (var i = 0; i < atomCount; i++) {
var n = atoms[i].bondCount;
if (n == 0 || n != atoms[i].bonds.length) atoms[i].bonds = JU.AU.arrayCopyObject(atoms[i].bonds, n);
}
var s = null;
var g =  new JS.SmilesGenerator();
if (points != null) g.polySmilesCenter = center;
this.clearExceptions();
s = g.getSmiles(this, atoms, atomCount, JU.BSUtil.newBitSet2(0, atomCount), null, flags | 4096 | 16 | 32);
if ((flags & 65536) == 65536) {
s = ((flags & 131072) == 0 ? "" : "//* " + center + " *//\t") + "[" + JU.Elements.elementSymbolFromNumber(center.getElementNumber()) + "@PH" + atomCount + (details == null ? "" : "/" + details + "/") + "]." + s;
}return s;
}, "JU.Node,~A,~N,~A,~N,~S");
Clazz_overrideMethod(c$, "getCorrelationMaps", 
function(pattern, atoms, atomCount, bsSelected, flags){
return this.matchPriv(pattern, atoms, atomCount, bsSelected, null, true, flags, 3, null);
}, "~O,~A,~N,JU.BS,~N");
Clazz_defineMethod(c$, "matchPriv", 
function(pattern, atoms, ac, bsSelected, bsAromatic, doTestAromatic, flags, mode, searchTarget){
this.clearExceptions();
try {
var isCompiled = (Clazz_instanceOf(pattern,"JS.SmilesSearch"));
if (isCompiled) {
flags |= 2;
(pattern).reset();
}var isSmarts = ((flags & 2) == 2);
var searchPattern = (isCompiled ? pattern : JS.SmilesParser.newSearch(pattern == null ? null : pattern.toString(), isSmarts, false));
if (searchTarget != null) searchTarget.setFlags(flags | searchTarget.flags | (isCompiled ? 0 : JS.SmilesParser.getFlags(pattern.toString())));
return this.matchPattern(searchPattern, atoms, ac, bsSelected, bsAromatic, doTestAromatic, flags, mode, searchTarget);
} catch (e) {
if (Clazz_exceptionOf(e, Exception)){
if (JU.Logger.debugging) e.printStackTrace();
if (JS.InvalidSmilesException.getLastError() == null) this.clearExceptions();
throw  new JS.InvalidSmilesException(JS.InvalidSmilesException.getLastError());
} else {
throw e;
}
}
}, "~O,~A,~N,JU.BS,JU.BS,~B,~N,~N,JS.SmilesSearch");
Clazz_defineMethod(c$, "matchPattern", 
function(search, atoms, ac, bsSelected, bsAromatic, doTestAromatic, flags, mode, searchTarget){
var isSmarts = ((flags & 2) == 2);
this.okMF = true;
if (searchTarget != null) {
if (searchTarget.targetSet) {
search.setTarget(searchTarget);
} else {
search.haveSmilesTarget = true;
bsAromatic =  new JU.BS();
searchTarget.createTopoMap(bsAromatic);
atoms = searchTarget.target.nodes;
ac = searchTarget.target.nodes.length;
if (isSmarts) {
var a1 = searchTarget.elementCounts;
var a2 = search.elementCounts;
var n = search.elementNumberMax;
if (n <= searchTarget.elementNumberMax) {
for (var i = 1; i <= n; i++) {
if (a1[i] < a2[i]) {
this.okMF = false;
break;
}}
} else {
this.okMF = false;
}} else {
var mf = search.getMFArray(true, null, false);
var mft = searchTarget.getMFArray(true, null, false);
var n = searchTarget.elementNumberMax;
if (n == search.elementNumberMax) {
for (var i = 2; i <= n; i++) {
if (mf[i] != mft[i]) {
this.okMF = false;
break;
}}
} else {
this.okMF = false;
}}}}if (this.okMF) {
if (!isSmarts && !search.patternAromatic) {
if (bsAromatic == null) bsAromatic =  new JU.BS();
search.normalizeAromaticity(bsAromatic);
search.isNormalized = true;
}if (!search.targetSet) search.target.setAtoms(atoms, ac, bsSelected);
if (search.targetSet || ac != 0 && (bsSelected == null || !bsSelected.isEmpty())) {
var is3D = search.targetSet || !(Clazz_instanceOf(atoms[0],"JS.SmilesAtom"));
search.getSelections();
if (!doTestAromatic) search.target.bsAromatic = bsAromatic;
if (!search.target.hasRingData(flags)) search.setRingData(null, null, is3D || doTestAromatic || search.patternAromatic);
search.exitFirstMatch = ((flags & 8) == 8);
search.mapUnique = ((flags & 128) == 128);
}}switch (mode) {
case 1:
search.asVector = false;
return (this.okMF ? search.search() :  new JU.BS());
case 2:
if (!this.okMF) return  new Array(0);
search.asVector = true;
var vb = search.search();
return vb.toArray( new Array(vb.size()));
case 4:
if (!this.okMF) return "";
search.exitFirstMatch = true;
search.setAtropicity = true;
search.search();
return search.atropKeys;
case 3:
if (!this.okMF) return  Clazz_newIntArray (0, 0, 0);
search.getMaps = true;
search.setFlags(flags | search.flags);
var vl = search.search();
return vl.toArray(JU.AU.newInt2(vl.size()));
case 5:
if (!this.okMF) return Boolean.FALSE;
search.retBoolean = true;
search.setFlags(flags | search.flags);
return search.search();
}
return null;
}, "JS.SmilesSearch,~A,~N,JU.BS,JU.BS,~B,~N,~N,JS.SmilesSearch");
Clazz_overrideMethod(c$, "cleanSmiles", 
function(smiles){
return JS.SmilesParser.cleanPattern(smiles);
}, "~S");
Clazz_overrideMethod(c$, "getMapForJME", 
function(jme, at, bsAtoms){
try {
var molecule = JS.SmilesMatcher.jmeToMolecule(jme);
var bs = JU.BSUtil.newBitSet2(0, molecule.ac);
var s = this.getSmiles(molecule.patternAtoms, molecule.ac, bs, null, 34);
var map = this.getCorrelationMaps(s, molecule.patternAtoms, molecule.ac, bs, 42);
var map2 = this.getCorrelationMaps(s, at, bsAtoms.cardinality(), bsAtoms, 42);
return  Clazz_newArray(-1, [map[0], map2[0]]);
} catch (e) {
if (Clazz_exceptionOf(e, Exception)){
e.printStackTrace();
} else {
throw e;
}
}
return null;
}, "~S,~A,JU.BS");
c$.jmeToMolecule = Clazz_defineMethod(c$, "jmeToMolecule", 
function(jme){
var molecule =  new JS.SmilesSearch();
var tokens = JU.PT.getTokens(jme);
var nAtoms = JU.PT.parseInt(tokens[0]);
var nBonds = JU.PT.parseInt(tokens[1]);
var pt = 2;
for (var i = 0; i < nAtoms; i++, pt += 3) {
var sa = tokens[pt];
var a = molecule.addAtom();
var ic = sa.indexOf("+");
var charge = 0;
if (ic >= 0) {
charge = (ic == sa.length - 1 ? 1 : JU.PT.parseInt(sa.substring(ic + 1)));
} else if ((ic = sa.indexOf("-")) >= 0) {
charge = JU.PT.parseInt(sa.substring(ic));
}a.setCharge(charge);
a.setSymbol(ic < 0 ? sa : sa.substring(0, ic));
}
for (var i = 0; i < nBonds; i++) {
var ia = JU.PT.parseInt(tokens[pt++]) - 1;
var ib = JU.PT.parseInt(tokens[pt++]) - 1;
var iorder = JU.PT.parseInt(tokens[pt++]);
var a1 = molecule.patternAtoms[ia];
var a2 = molecule.patternAtoms[ib];
var order = 1;
switch (iorder) {
default:
case 1:
break;
case 2:
order = 2;
break;
case 3:
order = 3;
break;
}
 new JS.SmilesBond(a1, a2, order, false).index = i;
}
molecule.isSmarts = true;
molecule.set();
return molecule;
}, "~S");
Clazz_overrideMethod(c$, "getSmilesFromJME", 
function(jme){
try {
var molecule = JS.SmilesMatcher.jmeToMolecule(jme);
var bs = JU.BSUtil.newBitSet2(0, molecule.ac);
return this.getSmiles(molecule.patternAtoms, molecule.ac, bs, null, 1);
} catch (e) {
if (Clazz_exceptionOf(e, Exception)){
return null;
} else {
throw e;
}
}
}, "~S");
Clazz_overrideMethod(c$, "compileSmartsPattern", 
function(pattern){
pattern = JS.SmilesParser.cleanPattern(pattern);
return JS.SmilesParser.newSearch(pattern, true, false);
}, "~S");
Clazz_overrideMethod(c$, "compileSearchTarget", 
function(atoms, atomCount, bsSelected){
var ss =  new JS.SmilesSearch();
ss.target.setAtoms(atoms, atomCount, bsSelected);
ss.targetSet = true;
return ss;
}, "~A,~N,JU.BS");
Clazz_overrideMethod(c$, "hasStructure", 
function(pattern, smilesSet, flags){
var ret =  Clazz_newIntArray (smilesSet.length, 0);
if ((flags & 1) != 1) {
flags = flags | 2;
}this.clearExceptions();
if ((typeof(pattern)=='string')) pattern = JS.SmilesParser.cleanPattern(pattern);
try {
var search = ((typeof(pattern)=='string') ? JS.SmilesParser.newSearch(pattern, true, false) : pattern);
for (var i = 0; i < smilesSet.length; i++) {
var smiles = smilesSet[i];
var searchTarget;
if ((typeof(smiles)=='string')) {
searchTarget = this.newSearch(smiles);
searchTarget.setFlags(searchTarget.flags | ((typeof(pattern)=='string') ? JS.SmilesParser.getFlags(pattern) : 0));
} else {
searchTarget = smiles;
}try {
this.clearExceptions();
ret[i] = (this.matchPattern(search, null, 0, null, null, false, flags | 8, 5, searchTarget) === Boolean.TRUE ? 1 : 0);
} catch (e) {
if (Clazz_exceptionOf(e, Exception)){
ret[i] = -1;
e.printStackTrace();
} else {
throw e;
}
}
}
} catch (e) {
if (Clazz_exceptionOf(e, Exception)){
if (JU.Logger.debugging) e.printStackTrace();
if (JS.InvalidSmilesException.getLastError() == null) this.clearExceptions();
throw  new JS.InvalidSmilesException(JS.InvalidSmilesException.getLastError());
} else {
throw e;
}
}
return ret;
}, "~O,~A,~N");
c$.j2sHeadless = true;
});
;//5.0.1-v7 Tue Feb 10 12:29:49 CST 2026
Clazz_declarePackage("JS");
Clazz_load(["java.lang.Exception"], "JS.InvalidSmilesException", null, function(){
var c$ = Clazz_declareType(JS, "InvalidSmilesException", Exception);
Clazz_makeConstructor(c$, 
function(message){
Clazz_superConstructor(this, JS.InvalidSmilesException, [message]);
JS.InvalidSmilesException.lastError = (message.startsWith("Jmol SMILES") ? message : "Jmol SMILES Exception: " + message);
}, "~S");
c$.getLastError = Clazz_defineMethod(c$, "getLastError", 
function(){
return JS.InvalidSmilesException.lastError;
});
c$.clear = Clazz_defineMethod(c$, "clear", 
function(){
JS.InvalidSmilesException.lastError = null;
});
Clazz_overrideMethod(c$, "getMessage", 
function(){
return JS.InvalidSmilesException.lastError;
});
c$.lastError = null;
});
;//5.0.1-v7 Thu Feb 05 13:38:23 CST 2026
Clazz_declarePackage("JS");
Clazz_load(["JU.JmolMolecule", "JU.BS", "$.Lst"], "JS.SmilesSearch", ["java.util.Hashtable", "JU.AU", "$.SB", "JS.InvalidSmilesException", "$.SmilesAromatic", "$.SmilesAtom", "$.SmilesBond", "$.SmilesMeasure", "$.SmilesParser", "$.SmilesStereo", "$.VTemp", "JU.BSUtil", "$.Logger"], function(){
var c$ = Clazz_decorateAsClass(function(){
this.isSmarts = false;
this.top = null;
this.target = null;
this.pattern = null;
this.patternAtoms = null;
this.v = null;
this.targetSet = false;
this.aromaticOpen = false;
this.aromaticStrict = false;
this.aromaticPlanar = false;
this.aromaticDouble = false;
this.aromaticMMFF94 = false;
this.aromaticDefined = false;
this.aromaticUnknown = false;
this.noAromatic = false;
this.ignoreAtomClass = false;
this.ignoreElement = false;
this.ignoreStereochemistry = false;
this.invertStereochemistry = false;
this.exitFirstMatch = false;
this.groupByModel = false;
this.setAtropicity = false;
this.patternAromatic = false;
this.haveSmilesTarget = false;
this.isTopology = false;
this.patternBioSequence = false;
this.subSearches = null;
this.haveSelected = false;
this.haveBondStereochemistry = false;
this.stereo = null;
this.needRingData = false;
this.needAromatic = true;
this.needRingMemberships = false;
this.nDouble = 0;
this.ringDataMax = -2147483648;
this.measures = null;
this.flags = 0;
this.atropKeys = null;
this.lastChainAtom = null;
this.asVector = false;
this.getMaps = false;
this.retBoolean = false;
this.isNormalized = false;
this.haveComponents = false;
this.isSilent = false;
this.isRingCheck = false;
this.bsFound = null;
this.htNested = null;
this.nNested = 0;
this.nestedBond = null;
this.vReturn = null;
this.uniqueList = null;
this.bsReturn = null;
this.bsCheck = null;
this.mapUnique = false;
this.polyhedronStereo = null;
this.polyAtom = null;
this.autoAddImplicitH = true;
this.pattern0 = null;
Clazz_instantialize(this, arguments);}, JS, "SmilesSearch", JU.JmolMolecule);
Clazz_prepareFields (c$, function(){
this.patternAtoms =  new Array(16);
this.measures =  new JU.Lst();
this.bsFound =  new JU.BS();
this.bsReturn =  new JU.BS();
});
Clazz_makeConstructor(c$, 
function(){
Clazz_superConstructor (this, JS.SmilesSearch, []);
this.top = this;
this.target =  new JS.SmilesSearch.SmilesTarget();
this.v =  new JS.VTemp();
});
c$.isRingBond = Clazz_defineMethod(c$, "isRingBond", 
function(ringSets, bsAromaticRings, a1, a2){
if (ringSets != null) {
for (var i = ringSets.size(); --i >= 0; ) {
var bsRing = ringSets.get(i);
if (bsRing.get(a1) && bsRing.get(a2)) {
if (bsAromaticRings == null || bsAromaticRings.get(i)) return true;
}}
}return false;
}, "JU.Lst,JU.BS,~N,~N");
Clazz_defineMethod(c$, "setTarget", 
function(s){
this.target = s.target;
this.targetSet = true;
}, "JS.SmilesSearch");
Clazz_defineMethod(c$, "setTop", 
function(parent){
while (parent.top !== parent) parent = parent.top;

this.top = parent;
}, "JS.SmilesSearch");
c$.addFlags = Clazz_defineMethod(c$, "addFlags", 
function(flags, strFlags){
if (strFlags.indexOf("OPEN") >= 0) flags |= 5;
if (strFlags.indexOf("BIO") >= 0) flags |= 1048576;
if (strFlags.indexOf("HYDROGEN2") >= 0) flags |= 8192;
 else if (strFlags.indexOf("HYDROGEN") >= 0) flags |= 4096;
if (strFlags.indexOf("FIRSTMATCHONLY") >= 0) flags |= 8;
if (strFlags.indexOf("STRICT") >= 0) flags |= 256;
if (strFlags.indexOf("PLANAR") >= 0) flags |= 1024;
if (strFlags.indexOf("NOAROMATIC") >= 0 || strFlags.indexOf("NONAROMATIC") >= 0) flags |= 16;
if (strFlags.indexOf("AROMATICDOUBLE") >= 0) flags |= 512;
if (strFlags.indexOf("AROMATICDEFINED") >= 0) flags |= 128;
if (strFlags.indexOf("MMFF94") >= 0) flags |= 768;
if (strFlags.indexOf("ALLCOMPONENTS") >= 0) flags |= 32768;
if (strFlags.indexOf("TOPOLOGY") >= 0) flags |= 16384;
if (strFlags.indexOf("NOATOMCLASS") >= 0) flags |= 2048;
if (strFlags.indexOf("NOSTEREO") >= 0) {
flags |= 32;
} else if (strFlags.indexOf("INVERTSTEREO") >= 0) {
if ((flags & 64) != 0) flags &= -65;
 else flags |= 64;
}if (strFlags.indexOf("ATOMCOMMENT") >= 0) flags |= 131072;
if (strFlags.indexOf("GROUPBYMODEL") >= 0) flags |= 67108864;
if ((flags & 1048576) == 1048576) {
if (strFlags.indexOf("NOCOMMENT") >= 0) flags |= 34603008;
if (strFlags.indexOf("UNMATCHED") >= 0) flags |= 3145728;
if (strFlags.indexOf("COVALENT") >= 0) flags |= 5242880;
if (strFlags.indexOf("HBOND") >= 0) flags |= 9437184;
}return flags;
}, "~N,~S");
Clazz_defineMethod(c$, "reset", 
function(){
this.vReturn = null;
this.noAromatic = false;
this.exitFirstMatch = false;
this.flags = 0;
});
Clazz_defineMethod(c$, "setFlags", 
function(flags){
this.flags = flags;
this.exitFirstMatch = new Boolean (this.exitFirstMatch | ((flags & 8) == 8)).valueOf();
this.aromaticOpen = ((flags & 5) == 5);
this.aromaticStrict = ((flags & 256) == 256);
this.aromaticPlanar = ((flags & 1024) == 1024);
this.aromaticMMFF94 = ((flags & 768) == 768);
this.aromaticDouble = ((flags & 512) == 512);
this.aromaticDefined = ((flags & 128) == 128);
this.noAromatic = new Boolean (this.noAromatic | ((flags & 16) == 16)).valueOf();
this.aromaticUnknown = !this.noAromatic && !this.aromaticOpen && !this.aromaticDouble && !this.aromaticStrict && !this.aromaticPlanar && !this.aromaticMMFF94 && !this.aromaticDefined;
this.groupByModel = ((flags & 67108864) == 67108864);
this.ignoreAtomClass = ((flags & 2048) == 2048);
this.ignoreStereochemistry = ((flags & 32) == 32);
this.invertStereochemistry = !this.ignoreStereochemistry && ((flags & 64) == 64);
this.ignoreElement = ((flags & 16384) == 16384);
}, "~N");
Clazz_defineMethod(c$, "set", 
function(){
if (this.patternAtoms.length > this.ac) this.patternAtoms = JU.AU.arrayCopyObject(this.patternAtoms, this.ac);
this.nodes = this.patternAtoms;
this.isTopology = true;
this.patternAromatic = false;
this.patternBioSequence = true;
for (var i = this.ac; --i >= 0; ) {
var atom = this.patternAtoms[i];
if (this.isTopology && atom.isDefined()) this.isTopology = false;
if (!atom.isBioResidue) this.patternBioSequence = false;
if (atom.isAromatic) this.patternAromatic = true;
atom.setBondArray();
if (this.autoAddImplicitH && !this.isSmarts && atom.bioType == '\0' && !atom.setHydrogenCount()) throw  new JS.InvalidSmilesException("unbracketed atoms must be one of: B, C, N, O, P, S, F, Cl, Br, I, *,");
}
if (this.haveComponents) {
for (var i = this.ac; --i >= 0; ) {
var a = this.patternAtoms[i];
var bonds = a.bonds;
var ia = a.component;
for (var j = a.bondCount; --j >= 0; ) {
var b = bonds[j];
var ib;
if (b.isConnection && b.atom2 === a && (ib = b.atom1.component) != ia) {
for (var k = this.ac; --k >= 0; ) if (this.patternAtoms[k].component == ia) this.patternAtoms[k].component = ib;

}}
}
}});
Clazz_defineMethod(c$, "addAtom", 
function(){
return this.appendAtom( new JS.SmilesAtom());
});
Clazz_defineMethod(c$, "appendAtom", 
function(sAtom){
if (this.ac >= this.patternAtoms.length) this.patternAtoms = JU.AU.doubleLength(this.patternAtoms);
return this.patternAtoms[this.ac] = sAtom.setIndex(this.ac++);
}, "JS.SmilesAtom");
Clazz_defineMethod(c$, "addNested", 
function(pattern){
if (this.htNested == null) this.htNested =  new java.util.Hashtable();
this.setNested(++this.nNested, pattern);
return this.nNested;
}, "~S");
Clazz_defineMethod(c$, "clear", 
function(){
this.bsReturn.clearAll();
this.nNested = 0;
this.htNested = null;
this.nestedBond = null;
this.clearBsFound(-1);
});
Clazz_defineMethod(c$, "clearBsFound", 
function(iAtom){
if (iAtom < 0) {
if (this.bsCheck == null) {
this.bsFound.clearAll();
}} else this.bsFound.clear(iAtom);
}, "~N");
Clazz_defineMethod(c$, "setNested", 
function(iNested, o){
this.top.htNested.put("_" + iNested, o);
}, "~N,~O");
Clazz_defineMethod(c$, "getNested", 
function(iNested){
return this.top.htNested.get("_" + iNested);
}, "~N");
Clazz_defineMethod(c$, "getMissingHydrogenCount", 
function(){
var n = 0;
var nH;
for (var i = 0; i < this.ac; i++) if ((nH = this.patternAtoms[i].explicitHydrogenCount) >= 0) n += nH;

return n;
});
Clazz_defineMethod(c$, "setRingData", 
function(bsA, vRings, doProcessAromatic){
if (this.isTopology || this.patternBioSequence) this.needAromatic = false;
this.needAromatic = new Boolean (this.needAromatic &( new Boolean ((bsA == null) & !this.noAromatic).valueOf())).valueOf();
if (this.needAromatic) this.needRingData = true;
if (!this.needAromatic) {
this.target.bsAromatic.clearAll();
if (bsA != null) this.target.bsAromatic.or(bsA);
if (!this.needRingMemberships && !this.needRingData) return;
}this.getRingData(vRings, this.needRingData, doProcessAromatic);
}, "JU.BS,~A,~B");
Clazz_defineMethod(c$, "getRingData", 
function(vRings, needRingData, doTestAromatic){
var isStrict = (this.needAromatic && (this.aromaticStrict || !this.aromaticOpen && !this.aromaticPlanar));
if (isStrict && this.aromaticUnknown) {
if (this.target.ac > 0 && this.target.nodes[this.target.bsSelected.nextSetBit(0)].modelIsRawPDB()) isStrict = false;
}var isOpenNotStrict = (this.needAromatic && this.aromaticOpen && !this.aromaticStrict);
var checkExplicit = (this.needAromatic && !isStrict);
var doFinalize = (this.needAromatic && doTestAromatic && (isStrict || isOpenNotStrict));
var setAromatic = (this.needAromatic && !this.aromaticDefined);
var aromaticMax = 7;
var lstAromatic = (vRings == null ?  new JU.Lst() : (vRings[3] =  new JU.Lst()));
var lstSP2 = (doFinalize ?  new JU.Lst() : null);
var strictness = (!isStrict ? 0 : this.aromaticMMFF94 ? 2 : 1);
if (this.needAromatic && this.aromaticDefined) {
this.target.checkAromaticDefined();
strictness = 0;
}this.ringDataMax = this.target.setRingData(strictness, needRingData, this.ringDataMax);
if (this.target.selectedAtomCount < 3) return;
var s = "****";
var max = this.ringDataMax;
while (s.length < max) s += s;

var eCounts = (doFinalize && setAromatic ?  Clazz_newIntArray (this.target.ac, 0) : null);
var justCheckBonding = (setAromatic && (isOpenNotStrict || Clazz_instanceOf(this.target.nodes[0],"JS.SmilesAtom")));
for (var i = 3; i <= max; i++) {
if (i > this.target.ac) break;
var smarts = "*1" + s.substring(0, i - 2) + "*1";
var search = JS.SmilesParser.newSearch(smarts, true, true);
var vR = this.subsearch(search, 2);
if (vRings != null && i <= 5) {
var v =  new JU.Lst();
for (var j = vR.size(); --j >= 0; ) v.addLast(vR.get(j));

vRings[i - 3] = v;
}if (vR.size() == 0) continue;
if (setAromatic && i >= 4 && i <= aromaticMax) {
JS.SmilesAromatic.setAromatic(i, this.target.nodes, this.target.bsSelected, vR, this.target.bsAromatic, strictness, isOpenNotStrict, justCheckBonding, checkExplicit, this.v, lstAromatic, lstSP2, eCounts, doTestAromatic);
}if (needRingData) {
this.target.ringData[i] =  new JU.BS();
for (var k = vR.size(); --k >= 0; ) {
var r = vR.get(k);
this.target.ringData[i].or(r);
for (var j = r.nextSetBit(0); j >= 0; j = r.nextSetBit(j + 1)) this.target.ringCounts[j]++;

}
}}
if (this.needAromatic) {
if (doFinalize) JS.SmilesAromatic.finalizeAromatic(this.target.nodes, this.target.bsAromatic, lstAromatic, lstSP2, eCounts, isOpenNotStrict, isStrict);
this.target.finalizeAromatic(lstAromatic);
}if (needRingData) {
this.target.finalizeRingData();
}}, "~A,~B,~B");
Clazz_defineMethod(c$, "subsearch", 
function(search, submode){
search.mapUnique = this.mapUnique;
search.target = this.target;
search.htNested = this.htNested;
search.haveSmilesTarget = this.haveSmilesTarget;
search.bsCheck = this.bsCheck;
search.isSmarts = true;
switch (submode) {
case 1:
search.exitFirstMatch = false;
break;
case 2:
search.isRingCheck = true;
search.isSilent = true;
search.asVector = true;
break;
case 3:
search.ignoreAtomClass = this.ignoreAtomClass;
search.aromaticDouble = this.aromaticDouble;
search.haveSelected = this.haveSelected;
search.exitFirstMatch = this.exitFirstMatch;
search.getMaps = this.getMaps;
search.retBoolean = this.retBoolean;
search.asVector = this.asVector;
search.vReturn = this.vReturn;
search.bsReturn = this.bsReturn;
search.haveBondStereochemistry = this.haveBondStereochemistry;
break;
}
return search.search2(submode == 1);
}, "JS.SmilesSearch,~N");
Clazz_defineMethod(c$, "search", 
function(){
this.bsReturn.clearAll();
return this.search2(false);
});
Clazz_defineMethod(c$, "search2", 
function(firstAtomOnly){
this.setFlags(this.flags);
if (!this.isRingCheck && JU.Logger.debuggingHigh && !this.isSilent) JU.Logger.debug("SmilesSearch processing " + this.pattern);
if (this.vReturn == null && (this.asVector || this.getMaps)) this.vReturn =  new JU.Lst();
if (this.subSearches != null) {
for (var i = 0; i < this.subSearches.length; i++) {
if (this.subSearches[i] == null) continue;
this.subsearch(this.subSearches[i], 3);
if (this.exitFirstMatch) {
if (this.vReturn == null ? this.bsReturn.nextSetBit(0) >= 0 : this.vReturn.size() > 0) break;
}}
} else if (this.ac > 0 && this.ac <= this.target.selectedAtomCount) {
if (this.nestedBond == null) {
this.clearBsFound(-1);
} else {
this.bsReturn.clearAll();
}this.nextPatternAtom(-1, -1, firstAtomOnly, -1);
}return (this.asVector || this.getMaps ? this.vReturn : !this.retBoolean ? this.bsReturn : Boolean.$valueOf(!this.bsReturn.isEmpty()));
}, "~B");
Clazz_defineMethod(c$, "nextPatternAtom", 
function(atomNum, iAtom, firstAtomOnly, c){
var jmolAtom;
var jmolBonds;
if (++atomNum < this.ac) {
var newPatternAtom = this.patternAtoms[atomNum];
var newPatternBond = (iAtom >= 0 ? newPatternAtom.getBondTo(null) : atomNum == 0 ? this.nestedBond : null);
if (newPatternBond == null) {
var bs = JU.BSUtil.copy(this.bsFound);
var bs0 = JU.BSUtil.copy(this.bsFound);
if (newPatternAtom.notBondedIndex >= 0) {
var pa = this.patternAtoms[newPatternAtom.notBondedIndex];
var a = pa.getMatchingAtom();
if (pa.isBioAtom) {
var ii = a.getOffsetResidueAtom("\0", 1);
if (ii >= 0) bs.set(ii);
ii = a.getOffsetResidueAtom("\0", -1);
if (ii >= 0) bs.set(ii);
} else if (pa === this.polyAtom) {
bs.set(pa.getMatchingAtomIndex());
} else {
jmolBonds = a.getEdges();
for (var k = 0; k < jmolBonds.length; k++) bs.set(jmolBonds[k].getOtherNode(a).getIndex());

}}var skipGroup = ((newPatternAtom.isBioAtomWild));
var j1 = this.target.bsSelected.nextSetBit(0);
j1 = (skipGroup && j1 >= 0 ? this.target.nodes[j1].getOffsetResidueAtom("\0", j1) : j1);
var oldJmolComponent;
var oldPatternComponent = (atomNum > 0 ? this.patternAtoms[atomNum - 1] : newPatternAtom).component;
var thisPatternComponent = newPatternAtom.component;
var checkComponents = this.haveComponents && thisPatternComponent != -2147483648;
for (var j = j1; j >= 0; j = this.target.bsSelected.nextSetBit(j + 1)) {
if (!bs.get(j) && !this.bsFound.get(j)) {
jmolAtom = this.target.nodes[j];
if (checkComponents && !this.isRingCheck) {
c = (this.groupByModel ? jmolAtom.getModelIndex() : jmolAtom.getMoleculeNumber(false));
oldJmolComponent = (atomNum > 0 ? this.patternAtoms[atomNum - 1].matchingComponent : c);
if ((oldPatternComponent == thisPatternComponent) != (oldJmolComponent == c)) continue;
}if (!this.nextTargetAtom(newPatternAtom, jmolAtom, atomNum, j, firstAtomOnly, c)) return false;
}if (skipGroup) {
j1 = this.target.nodes[j].getOffsetResidueAtom(newPatternAtom.bioAtomName, 1);
if (j1 >= 0) j = j1 - 1;
}}
this.bsFound = bs0;
return true;
}jmolAtom = newPatternBond.atom1.getMatchingAtom();
switch (newPatternBond.order) {
case 96:
var nextGroupAtom = jmolAtom.getOffsetResidueAtom(newPatternAtom.bioAtomName, 1);
if (nextGroupAtom >= 0) {
var bs = JU.BSUtil.copy(this.bsFound);
jmolAtom.getGroupBits(this.bsFound);
if (this.doCheckAtom(nextGroupAtom) && !this.nextTargetAtom(newPatternAtom, this.target.nodes[nextGroupAtom], atomNum, nextGroupAtom, firstAtomOnly, c)) return false;
this.bsFound = bs;
}return true;
case 112:
var vLinks =  new JU.Lst();
jmolAtom.getCrossLinkVector(vLinks, true, true);
var bs = JU.BSUtil.copy(this.bsFound);
jmolAtom.getGroupBits(this.bsFound);
for (var j = 2; j < vLinks.size(); j += 3) {
var ia = vLinks.get(j).intValue();
if (this.doCheckAtom(ia) && !this.nextTargetAtom(newPatternAtom, this.target.nodes[ia], atomNum, ia, firstAtomOnly, c)) return false;
}
this.bsFound = bs;
return true;
}
jmolBonds = jmolAtom.getEdges();
if (jmolBonds != null) for (var j = 0; j < jmolBonds.length; j++) {
var ia = jmolAtom.getBondedAtomIndex(j);
if (this.doCheckAtom(ia) && !this.nextTargetAtom(newPatternAtom, this.target.nodes[ia], atomNum, ia, firstAtomOnly, c)) return false;
}
this.clearBsFound(iAtom);
return true;
}if (!this.ignoreStereochemistry && !this.isRingCheck) {
if (JU.Logger.debuggingHigh) {
for (var i = 0; i < atomNum; i++) JU.Logger.debug("pattern atoms " + this.patternAtoms[i] + " " + this.patternAtoms[i].matchingComponent);

JU.Logger.debug("--ss-- " + this.bsFound.cardinality());
}if (!this.checkStereochemistry()) return true;
}var bs =  new JU.BS();
var nMatch = 0;
for (var j = 0; j < this.ac; j++) {
var i = this.patternAtoms[j].getMatchingAtomIndex();
if (!firstAtomOnly && this.top.haveSelected && !this.patternAtoms[j].selected) continue;
nMatch++;
bs.set(i);
if (this.patternAtoms[j].isBioAtomWild) this.target.nodes[i].getGroupBits(bs);
if (firstAtomOnly) break;
if (!this.isSmarts) if (!this.setAtropicity && this.patternAtoms[j].explicitHydrogenCount > 0) {
var atom = this.target.nodes[i];
for (var k = 0, n = atom.getEdges().length; k < n; k++) {
var ia = atom.getBondedAtomIndex(k);
if (this.target.nodes[ia].getElementNumber() == 1) bs.set(ia);
}
}}
if (!this.isSmarts && bs.cardinality() != this.target.selectedAtomCount) return true;
if (this.bsCheck != null) {
if (firstAtomOnly) {
this.bsCheck.clearAll();
for (var j = 0; j < this.ac; j++) {
this.bsCheck.set(this.patternAtoms[j].getMatchingAtomIndex());
}
if (this.bsCheck.cardinality() != this.ac) return true;
} else {
if (bs.cardinality() != this.ac) return true;
}}this.bsReturn.or(bs);
if (this.getMaps) {
if (this.mapUnique) {
if (this.uniqueList == null) this.uniqueList =  new JU.Lst();
for (var j = this.uniqueList.size(); --j >= 0; ) if (this.uniqueList.get(j).equals(bs)) return true;

this.uniqueList.addLast(bs);
}var map =  Clazz_newIntArray (nMatch, 0);
for (var j = 0, nn = 0; j < this.ac; j++) {
if (!firstAtomOnly && this.top.haveSelected && !this.patternAtoms[j].selected) continue;
map[nn++] = this.patternAtoms[j].getMatchingAtomIndex();
}
this.vReturn.addLast(map);
return !this.exitFirstMatch;
}if (this.asVector) {
var isOK = true;
for (var j = this.vReturn.size(); --j >= 0 && isOK; ) isOK = !((this.vReturn.get(j)).equals(bs));

if (!isOK) return true;
this.vReturn.addLast(bs);
}if (this.isRingCheck) {
var bsRing =  new JU.BS();
for (var k = atomNum * 3 + 2; --k > atomNum; ) bsRing.set(this.patternAtoms[(k <= atomNum * 2 ? atomNum * 2 - k + 1 : k - 1) % atomNum].getMatchingAtomIndex());

this.target.ringSets.addLast(bsRing);
return true;
}if (this.exitFirstMatch) return false;
return (bs.cardinality() != this.target.selectedAtomCount);
}, "~N,~N,~B,~N");
Clazz_defineMethod(c$, "doCheckAtom", 
function(j){
return this.target.bsSelected.get(j) && !this.bsFound.get(j);
}, "~N");
Clazz_defineMethod(c$, "nextTargetAtom", 
function(patternAtom, jmolAtom, atomNum, iAtom, firstAtomOnly, c){
var jmolBonds;
if (!this.isRingCheck && !this.isTopology) {
if (patternAtom.subAtoms == null) {
if (!this.checkPrimitiveAtom(patternAtom, iAtom)) return true;
} else if (patternAtom.isAND) {
for (var i = 0; i < patternAtom.nSubAtoms; i++) if (!this.checkPrimitiveAtom(patternAtom.subAtoms[i], iAtom)) return true;

} else {
for (var i = 0; i < patternAtom.nSubAtoms; i++) if (!this.nextTargetAtom(patternAtom.subAtoms[i], jmolAtom, atomNum, iAtom, firstAtomOnly, c)) return false;

return true;
}}jmolBonds = jmolAtom.getEdges();
for (var i = patternAtom.getBondCount(); --i >= 0; ) {
var patternBond = patternAtom.getBond(i);
if (patternBond.getAtomIndex2() != patternAtom.index) continue;
var atom1 = patternBond.atom1;
var matchingAtom = atom1.getMatchingAtomIndex();
switch (patternBond.order) {
case 96:
case 112:
if (!this.checkMatchBond(patternAtom, atom1, patternBond, iAtom, matchingAtom, null)) return true;
break;
default:
var k = 0;
var jmolBond = null;
for (; k < jmolBonds.length; k++) if ((jmolBond = jmolBonds[k]).isCovalent() && (jmolBond.getAtomIndex1() == matchingAtom || jmolBond.getAtomIndex2() == matchingAtom)) break;

if (k == jmolBonds.length) return true;
if (!this.checkMatchBond(patternAtom, atom1, patternBond, iAtom, matchingAtom, jmolBond)) return true;
}
}
patternAtom = this.patternAtoms[patternAtom.index];
patternAtom.setMatchingAtom(this.target.nodes[iAtom], iAtom);
patternAtom.matchingComponent = c;
this.bsFound.set(iAtom);
if (!this.nextPatternAtom(atomNum, iAtom, firstAtomOnly, c)) return false;
if (iAtom >= 0) this.clearBsFound(iAtom);
return true;
}, "JS.SmilesAtom,JU.Node,~N,~N,~B,~N");
Clazz_defineMethod(c$, "checkPrimitiveAtom", 
function(patternAtom, iTarget){
if (patternAtom.nSubAtoms > 0) {
for (var i = 0; i < patternAtom.nSubAtoms; i++) if (this.checkPrimitiveAtom(patternAtom.subAtoms[i], iTarget)) return true;

return false;
}var targetAtom = this.target.nodes[iTarget];
var foundAtom = patternAtom.not;
while (true) {
if (patternAtom.iNested > 0) {
var o = this.getNested(patternAtom.iNested);
if (Clazz_instanceOf(o,"JS.SmilesSearch")) {
var search = o;
if (patternAtom.isBioAtom) search.nestedBond = patternAtom.getBondTo(null);
o = this.subsearch(search, 1);
if (o == null) o =  new JU.BS();
if (!patternAtom.isBioAtom) this.setNested(patternAtom.iNested, o);
}foundAtom = (patternAtom.not != ((o).get(iTarget)));
break;
}var na = targetAtom.getElementNumber();
var n = patternAtom.elementNumber;
if (na >= 0 && n >= 0 && n != na && !this.ignoreElement) break;
if (patternAtom.isBioResidue) {
var a = targetAtom;
if (patternAtom.bioAtomName != null && (patternAtom.isLeadAtom() ? !a.isLeadAtom() : !patternAtom.bioAtomName.equals(a.getAtomName().toUpperCase()))) break;
if (patternAtom.residueName != null && !patternAtom.residueName.equals(a.getGroup3(false).toUpperCase())) break;
if (patternAtom.residueNumber != -2147483648 && patternAtom.residueNumber != a.getResno()) break;
if (patternAtom.insCode != '\0' && patternAtom.insCode != a.getInsertionCode()) break;
if (patternAtom.residueChar != null || patternAtom.elementNumber == -2) {
var atype = a.getBioSmilesType();
var ptype = patternAtom.getBioSmilesType();
var ok = true;
var isNucleic = false;
switch ((ptype).charCodeAt(0)) {
case 0:
case 42:
ok = true;
break;
case 110:
ok = (atype == 'r' || atype == 'c');
isNucleic = true;
break;
case 114:
case 99:
isNucleic = true;
default:
ok = (atype == ptype);
break;
}
if (!ok) break;
var s = a.getGroup1('\0').toUpperCase();
var resChar = (patternAtom.residueChar == null ? '*' : patternAtom.residueChar.charAt(0));
var isOK = (resChar == s.charAt(0));
switch ((resChar).charCodeAt(0)) {
case 42:
isOK = true;
break;
case 78:
isOK = isNucleic ? (atype == 'r' || atype == 'c') : isOK;
break;
case 82:
isOK = isNucleic ? a.isPurine() : isOK;
break;
case 89:
isOK = isNucleic ? a.isPyrimidine() : isOK;
break;
}
if (!isOK) break;
}if (patternAtom.isBioAtom) {
if (patternAtom.notCrossLinked && a.getCrossLinkVector(null, true, true)) break;
}} else {
if (patternAtom.atomNumber != -2147483648 && patternAtom.atomNumber != targetAtom.getAtomNumber()) break;
if (patternAtom.jmolIndex >= 0 && targetAtom.getIndex() != patternAtom.jmolIndex) break;
if (patternAtom.atomType != null && !patternAtom.atomType.equals(targetAtom.getAtomType())) break;
if ((n = patternAtom.getAtomicMass()) != -2147483648 && (n >= 0 && n != (na = targetAtom.getIsotopeNumber()) || n < 0 && na != 0 && -n != na)) break;
if (!this.noAromatic && !patternAtom.aromaticAmbiguous && patternAtom.isAromatic != this.target.bsAromatic.get(iTarget)) break;
if ((n = patternAtom.getCharge()) != -2147483648 && n != targetAtom.getFormalCharge()) break;
n = patternAtom.getCovalentHydrogenCount() + patternAtom.explicitHydrogenCount;
if (n >= 0 && n != targetAtom.getTotalHydrogenCount()) break;
if ((n = patternAtom.implicitHydrogenCount) != -2147483648) {
na = targetAtom.getImplicitHydrogenCount();
if (n == -1 ? na == 0 : n != na) break;
}if (patternAtom.degree > 0 && patternAtom.degree != targetAtom.getCovalentBondCount()) break;
if (patternAtom.nonhydrogenDegree > 0 && patternAtom.nonhydrogenDegree != targetAtom.getCovalentBondCount() - targetAtom.getCovalentHydrogenCount()) break;
if (this.isSmarts && patternAtom.valence > 0 && patternAtom.valence != targetAtom.getTotalValence()) break;
if (patternAtom.connectivity > 0 && patternAtom.connectivity != targetAtom.getCovalentBondCountPlusMissingH()) break;
if (patternAtom.atomNumber != -2147483648 && patternAtom.atomNumber != targetAtom.getAtomNumber()) break;
if (patternAtom.jmolIndex >= 0 && targetAtom.getIndex() != patternAtom.jmolIndex) break;
if (patternAtom.atomType != null && !patternAtom.atomType.equals(targetAtom.getAtomType())) break;
if (!this.ignoreAtomClass || this.isSmarts) {
if (!Float.isNaN(patternAtom.atomClass) && patternAtom.atomClass != targetAtom.getFloatProperty("property_atomclass")) break;
}if (this.target.ringData != null) {
if (patternAtom.ringSize >= -1) {
if (patternAtom.ringSize <= 0) {
if ((this.target.ringCounts[iTarget] == 0) != (patternAtom.ringSize == 0)) break;
} else {
var rd = this.target.ringData[patternAtom.ringSize == 500 ? 5 : patternAtom.ringSize == 600 ? 6 : patternAtom.ringSize];
if (rd == null || !rd.get(iTarget)) break;
if (!this.noAromatic) if (patternAtom.ringSize == 500) {
if (!this.target.bsAromatic5.get(iTarget)) break;
} else if (patternAtom.ringSize == 600) {
if (!this.target.bsAromatic6.get(iTarget)) break;
}}}if (patternAtom.ringMembership >= -1) {
if (patternAtom.ringMembership == -1 ? this.target.ringCounts[iTarget] == 0 : this.target.ringCounts[iTarget] != patternAtom.ringMembership) break;
}if (patternAtom.ringConnectivity >= 0) {
n = this.target.ringConnections[iTarget];
if (patternAtom.ringConnectivity == -1 && n == 0 || patternAtom.ringConnectivity != -1 && n != patternAtom.ringConnectivity) break;
}}}foundAtom = !foundAtom;
break;
}
return foundAtom;
}, "JS.SmilesAtom,~N");
Clazz_defineMethod(c$, "checkMatchBond", 
function(patternAtom, atom1, patternBond, iAtom, matchingAtom, bond){
if (patternBond.bondsOr != null) {
for (var ii = 0; ii < patternBond.nBondsOr; ii++) if (this.checkMatchBond(patternAtom, atom1, patternBond.bondsOr[ii], iAtom, matchingAtom, bond)) return true;

return false;
}if (!this.isRingCheck && !this.isTopology) if (patternBond.nPrimitives == 0) {
if (!this.checkPrimitiveBond(patternBond, iAtom, matchingAtom, bond)) return false;
} else {
for (var i = 0; i < patternBond.nPrimitives; i++) {
var prim = patternBond.setPrimitive(i);
if (!this.checkPrimitiveBond(prim, iAtom, matchingAtom, bond)) return false;
}
}patternBond.matchingBond = bond;
return true;
}, "JS.SmilesAtom,JS.SmilesAtom,JS.SmilesBond,~N,~N,JU.Edge");
Clazz_defineMethod(c$, "checkPrimitiveBond", 
function(patternBond, iAtom1, iAtom2, bond){
var bondFound = false;
switch (patternBond.order) {
case 96:
return (patternBond.isNot != (this.target.nodes[iAtom2].getOffsetResidueAtom("\0", 1) == this.target.nodes[iAtom1].getOffsetResidueAtom("\0", 0)));
case 112:
return (patternBond.isNot != this.target.nodes[iAtom1].isCrossLinked(this.target.nodes[iAtom2]));
}
var isAromatic1 = (!this.noAromatic && this.target.bsAromatic.get(iAtom1));
var isAromatic2 = (!this.noAromatic && this.target.bsAromatic.get(iAtom2));
var order = bond.getCovalentOrder();
var patternOrder = patternBond.order;
if (isAromatic1 && isAromatic2) {
switch (patternOrder) {
case 17:
case 65:
bondFound = JS.SmilesSearch.isRingBond(this.target.ringSets, null, iAtom1, iAtom2);
break;
case 1:
bondFound = !this.isSmarts || !JS.SmilesSearch.isRingBond(this.target.ringSets, this.target.getBSAromaticRings(), iAtom1, iAtom2);
break;
case 2:
bondFound = this.isNormalized || order == 81 || this.aromaticDouble && (order == 2 || order == 514);
break;
case 65537:
case 65538:
bondFound = !patternBond.isNot;
break;
case 81:
case -1:
bondFound = true;
break;
}
} else {
switch (patternOrder) {
case 17:
if (!this.noAromatic) break;
case 81:
case -1:
bondFound = true;
break;
case 1:
case 1025:
case 1041:
switch (order) {
case 1:
case 1025:
case 1041:
bondFound = true;
break;
}
break;
case 65537:
case 65538:
switch (order) {
case 1:
case 65537:
case 65538:
bondFound = !patternBond.isNot;
break;
}
break;
case 2:
case 3:
case 4:
bondFound = (order == patternOrder);
break;
case 65:
bondFound = JS.SmilesSearch.isRingBond(this.target.ringSets, null, iAtom1, iAtom2);
break;
}
}return bondFound != patternBond.isNot;
}, "JS.SmilesBond,~N,~N,JU.Edge");
Clazz_defineMethod(c$, "checkStereochemistry", 
function(){
for (var i = 0; i < this.measures.size(); i++) if (!this.measures.get(i).check()) return false;

if (this.stereo != null && !this.stereo.checkStereoChemistry(this, this.v)) return false;
if (!this.haveBondStereochemistry) return true;
var lstAtrop = null;
var b = null;
for (var k = 0; k < this.ac; k++) {
var sAtom1 = this.patternAtoms[k];
var sAtom2 = null;
var sAtomDirected1 = null;
var sAtomDirected2 = null;
var dir1 = 0;
var dir2 = 0;
var bondType = 0;
var nBonds = sAtom1.getBondCount();
var isAtropisomer = false;
var indexOrder = true;
for (var j = 0; j < nBonds; j++) {
b = sAtom1.getBond(j);
var isAtom2 = (b.atom2 === sAtom1);
indexOrder = (b.atom1.index < b.atom2.index);
var type = b.getBondType();
switch (type) {
case 65537:
case 65538:
if (!indexOrder) continue;
case 2:
if (isAtom2) continue;
sAtom2 = b.atom2;
bondType = type;
isAtropisomer = (type != 2);
if (isAtropisomer) dir1 = (b.isNot ? -1 : 1);
break;
case 1025:
case 1041:
sAtomDirected1 = (isAtom2 ? b.atom1 : b.atom2);
dir1 = (isAtom2 != (type == 1025) ? 1 : -1);
break;
}
}
if (isAtropisomer) {
if (this.setAtropicity) {
if (lstAtrop == null) lstAtrop =  new JU.Lst();
lstAtrop.addLast(b);
continue;
}var b1 = sAtom1.getBond(b.atropType[0]);
if (b1 == null) return false;
sAtomDirected1 = b1.getOtherAtom(sAtom1);
b1 = sAtom2.getBond(b.atropType[1]);
if (b1 == null) return false;
sAtomDirected2 = b1.getOtherAtom(sAtom2);
if (JU.Logger.debugging) JU.Logger.info("atropisomer check for atoms " + sAtomDirected1 + sAtom1 + " " + sAtom2 + sAtomDirected2);
} else {
if (sAtom2 == null || dir1 == 0) continue;
var a10 = sAtom1;
var nCumulene = 0;
while (sAtom2.getBondCount() == 2 && sAtom2.getValence() == 4) {
nCumulene++;
var e2 = sAtom2.getEdges();
var e = e2[e2[0].getOtherNode(sAtom2) === a10 ? 1 : 0];
a10 = sAtom2;
sAtom2 = e.getOtherNode(sAtom2);
}
if (nCumulene % 2 == 1) continue;
nBonds = sAtom2.getBondCount();
for (var j = 0; j < nBonds && dir2 == 0; j++) {
b = sAtom2.getBond(j);
var type = b.getBondType();
switch (type) {
case 1025:
case 1041:
var isAtom2 = (b.atom2 === sAtom2);
sAtomDirected2 = (isAtom2 ? b.atom1 : b.atom2);
dir2 = (isAtom2 != (type == 1025) ? 1 : -1);
break;
}
}
if (dir2 == 0) continue;
}var dbAtom1 = sAtom1.getMatchingAtom();
var dbAtom2 = sAtom2.getMatchingAtom();
var dbAtom1a = sAtomDirected1.getMatchingAtom();
var dbAtom2a = sAtomDirected2.getMatchingAtom();
if (dbAtom1a == null || dbAtom2a == null) return false;
if (this.haveSmilesTarget) JS.SmilesSearch.setTopoCoordinates(dbAtom1, dbAtom2, dbAtom1a, dbAtom2a, bondType);
var d = JS.SmilesMeasure.setTorsionData(dbAtom1a, dbAtom1, dbAtom2, dbAtom2a, this.v, isAtropisomer);
if (isAtropisomer) {
d *= dir1 * (bondType == 65537 ? 1 : -1) * (indexOrder ? 1 : -1) * 1 * -1;
if (JU.Logger.debugging) JU.Logger.info("atrop dihedral " + d + " " + sAtom1 + " " + sAtom2 + " " + b);
if (d < 1) return false;
} else {
if (this.v.vTemp1.dot(this.v.vTemp2) * dir1 * dir2 < 0) return false;
}}
if (this.setAtropicity) {
this.atropKeys = "";
for (var i = 0; i < lstAtrop.size(); i++) this.atropKeys += "," + this.getAtropIndex(lstAtrop.get(i));

}return true;
});
Clazz_defineMethod(c$, "getAtropIndex", 
function(b){
var nodes =  new Array(4);
var s = "";
nodes[1] = b.atom1.getMatchingAtom();
nodes[2] = b.atom2.getMatchingAtom();
var b1 = b.atom1.bonds;
var a;
for (var i = b.atom1.getBondCount(); --i >= 0; ) {
if ((a = b1[i].getOtherNode(b.atom1)) !== b.atom2) {
s += (i + 1);
nodes[0] = a.getMatchingAtom();
break;
}}
b1 = b.atom2.bonds;
for (var i = 0; i <= b.atom2.getBondCount(); i++) {
if ((a = b1[i].getOtherNode(b.atom2)) !== b.atom1) {
s += (i + 1);
nodes[3] = a.getMatchingAtom();
break;
}}
if (s.equals("22")) s = "";
s = (JS.SmilesStereo.getAtropicStereoFlag(nodes) == 1 ? "" : "^") + s;
return (s + "   ").substring(0, 3);
}, "JS.SmilesBond");
c$.setTopoCoordinates = Clazz_defineMethod(c$, "setTopoCoordinates", 
function(dbAtom1, dbAtom2, dbAtom1a, dbAtom2a, bondType){
dbAtom1.set(-1, 0, 0);
dbAtom2.set(1, 0, 0);
if (bondType != 2) {
var bond = dbAtom1.getBondTo(dbAtom2);
var ok1 = dbAtom1.getBondedAtomIndex(bond.atropType[0]) == dbAtom1a.index;
var ok2 = dbAtom2.getBondedAtomIndex(bond.atropType[1]) == dbAtom2a.index;
var dir = (bond.order == 65537 ? 1 : -1) * (ok1 == ok2 ? 1 : -1);
dbAtom1a.set(-1, 1, 0);
dbAtom2a.set(1, 1, dir / 2.0 * 1 * -1);
return;
}var nBonds = 0;
var dir1 = 0;
var bonds = dbAtom1.getEdges();
for (var k = bonds.length; --k >= 0; ) {
var bond = bonds[k];
if (bond.order == 2) continue;
var atom = bond.getOtherNode(dbAtom1);
(atom).set(-1, (nBonds++ == 0) ? -1 : 1, 0);
var mode = (bond.getAtomIndex2() == dbAtom1.getIndex() ? nBonds : -nBonds);
switch (bond.order) {
case 1025:
dir1 = mode;
break;
case 1041:
dir1 = -mode;
}
}
var dir2 = 0;
nBonds = 0;
var atoms =  new Array(2);
bonds = dbAtom2.getEdges();
for (var k = bonds.length; --k >= 0; ) {
var bond = bonds[k];
if (bond.order == 2) continue;
var atom = bond.getOtherNode(dbAtom2);
atoms[nBonds] = atom;
(atom).set(1, (nBonds++ == 0) ? 1 : -1, 0);
var mode = (bond.getAtomIndex2() == dbAtom2.getIndex() ? nBonds : -nBonds);
switch (bond.order) {
case 1025:
dir2 = mode;
break;
case 1041:
dir2 = -mode;
}
}
if ((dir1 * dir2 > 0) == (Math.abs(dir1) % 2 == Math.abs(dir2) % 2)) {
var y = (atoms[0]).y;
(atoms[0]).y = (atoms[1]).y;
(atoms[1]).y = y;
}}, "JS.SmilesAtom,JS.SmilesAtom,JS.SmilesAtom,JS.SmilesAtom,~N");
Clazz_defineMethod(c$, "createTopoMap", 
function(bsAro){
var isForMF = (bsAro == null);
var nAtomsMissing = (this.autoAddImplicitH ? this.getMissingHydrogenCount() : 0);
var totalAtoms = this.ac + nAtomsMissing;
var atoms =  new Array(totalAtoms);
this.target.nodes = atoms;
for (var i = 0, ptAtom = 0; i < this.ac; i++, ptAtom++) {
var sAtom = this.patternAtoms[i];
var n = sAtom.explicitHydrogenCount;
if (n < 0 || !this.autoAddImplicitH) n = 0;
var atom = atoms[ptAtom] =  new JS.SmilesAtom().setTopoAtom(sAtom.component, ptAtom, sAtom.symbol, sAtom.getCharge(), i);
atom.implicitHydrogenCount = n;
if (isForMF) continue;
atom.mapIndex = i;
atom.stereo = sAtom.stereo;
atom.setAtomicMass(sAtom.getAtomicMass());
atom.bioAtomName = sAtom.bioAtomName;
atom.residueName = sAtom.residueName;
atom.residueChar = sAtom.residueChar;
atom.residueNumber = sAtom.residueNumber;
atom.atomNumber = sAtom.residueNumber;
atom.insCode = sAtom.insCode;
atom.hasDoubleBond = sAtom.hasDoubleBond;
atom.isAromatic = sAtom.isAromatic;
atom.atomClass = sAtom.atomClass;
atom.explicitHydrogenCount = 0;
atom.isBioAtom = sAtom.isBioAtom;
atom.bioType = sAtom.bioType;
atom.$isLeadAtom = sAtom.$isLeadAtom;
if (!isForMF && sAtom.isAromatic) bsAro.set(ptAtom);
sAtom.setMatchingAtom(null, ptAtom);
var bonds =  new Array(sAtom.getBondCount() + n);
atom.setBonds(bonds);
while (--n >= 0) {
var atomH = atoms[++ptAtom] =  new JS.SmilesAtom().setTopoAtom(atom.component, ptAtom, "H", 0, -1);
atomH.mapIndex = -i - 1;
atomH.setBonds( new Array(1));
var b =  new JS.SmilesBond(atom, atomH, 1, false);
if (JU.Logger.debugging) JU.Logger.info("" + b);
}
}
if (isForMF) return;
for (var i = 0; i < this.ac; i++) {
var sAtom = this.patternAtoms[i];
var i1 = sAtom.getMatchingAtomIndex();
var atom1 = atoms[i1];
var n = sAtom.getBondCount();
for (var j = 0; j < n; j++) {
var sBond = sAtom.getBond(j);
var firstAtom = (sBond.atom1 === sAtom);
if (firstAtom) {
var order = 1;
switch (sBond.order) {
case 1:
case 2:
case 3:
case 4:
case 1025:
case 1041:
case 65537:
case 65538:
case 112:
case 96:
order = sBond.order;
break;
case 17:
order = 514;
break;
}
var atom2 = atoms[sBond.atom2.getMatchingAtomIndex()];
var b =  new JS.SmilesBond(atom1, atom2, order, false);
b.isConnection = sBond.isConnection;
b.atropType = sBond.atropType;
b.isNot = sBond.isNot;
atom2.bondCount--;
if (JU.Logger.debugging) JU.Logger.info("" + b);
} else {
var atom2 = atoms[sBond.atom1.getMatchingAtomIndex()];
var b = atom2.getBondTo(atom1);
atom1.addBond(b);
}}
}
for (var i = 0; i < totalAtoms; i++) {
var a = atoms[i];
var bonds = a.bonds;
if (bonds.length < 2 || bonds[0].isFromPreviousTo(a)) continue;
for (var k = bonds.length; --k >= 1; ) if (bonds[k].isFromPreviousTo(a)) {
var b = bonds[k];
bonds[k] = bonds[0];
bonds[0] = b;
break;
}
}
if (!this.ignoreStereochemistry) for (var i = this.ac; --i >= 0; ) {
var sAtom = this.patternAtoms[i];
if (sAtom.stereo != null) sAtom.stereo.fixStereo(sAtom);
}
}, "JU.BS");
Clazz_defineMethod(c$, "normalizeAromaticity", 
function(bsAromatic){
var atoms = this.patternAtoms;
var ss =  new JS.SmilesSearch();
ss.noAromatic = this.noAromatic;
ss.setFlags(this.flags);
ss.target.nodes = atoms;
ss.target.ac = atoms.length;
ss.target.bsSelected = JU.BSUtil.newBitSet2(0, atoms.length);
var vRings = JU.AU.createArrayOfArrayList(4);
ss.setRingData(null, vRings, true);
bsAromatic.or(ss.target.bsAromatic);
if (!bsAromatic.isEmpty()) {
var lst = vRings[3];
if (lst != null) for (var i = lst.size(); --i >= 0; ) {
var bs = lst.get(i);
for (var j = bs.nextSetBit(0); j >= 0; j = bs.nextSetBit(j + 1)) {
var a = atoms[j];
if (a.isAromatic || a.elementNumber == -2 || a.elementNumber == 0) continue;
a.setSymbol(a.symbol.toLowerCase());
}
}
}}, "JU.BS");
Clazz_defineMethod(c$, "getSelections", 
function(){
var ht = this.top.htNested;
if (ht == null || this.target.nodes.length == 0) return;
var htNew =  new java.util.Hashtable();
for (var entry, $entry = ht.entrySet().iterator (); $entry.hasNext()&& ((entry = $entry.next ()) || true);) {
var key = entry.getValue().toString();
if (key.startsWith("select")) {
var bs = (htNew.containsKey(key) ? htNew.get(key) : this.target.nodes[0].findAtomsLike(key.substring(6)));
if (bs == null) bs =  new JU.BS();
htNew.put(key, bs);
entry.setValue(bs);
}}
});
Clazz_defineMethod(c$, "findImplicitHydrogen", 
function(atom){
var edges = atom.getEdges();
for (var i = edges.length; --i >= 0; ) {
var k = atom.getBondedAtomIndex(i);
if (this.target.nodes[k].getElementNumber() == 1 && !this.bsFound.get(k)) return this.target.nodes[k];
}
return null;
}, "JU.Node");
Clazz_defineMethod(c$, "toString", 
function(){
if (this.pattern0 != null) return this.pattern0;
if (this.targetSet) {
return "molecular formula: " + this.target.getMolecularFormula(true, null, false);
}var sb =  new JU.SB().append(this.pattern);
sb.append("\nmolecular formula: " + this.getMolecularFormula(true, null, false));
return sb.toString();
});
Clazz_overrideMethod(c$, "equals", 
function(ss){
return (Clazz_instanceOf(ss,"JS.SmilesSearch")) && (this.pattern0 == null ? (ss).pattern0 == null : this.pattern0.equals((ss).pattern0));
}, "~O");
Clazz_defineMethod(c$, "hashCode", 
function(){
return (this.pattern0 == null ? Clazz_superCall(this, JS.SmilesSearch, "hashCode", []) : this.pattern0.hashCode());
});
/*if3*/;(function(){
var c$ = Clazz_decorateAsClass(function(){
this.bsSelected = null;
this.selectedAtomCount = 0;
this.ringSets = null;
this.ringCount = 0;
this.ringData = null;
this.ringDataMax = 0;
this.ringCounts = null;
this.ringConnections = null;
this.bsAromatic = null;
this.bsAromatic5 = null;
this.bsAromatic6 = null;
this.bsAromaticRings = null;
this.$hasRingData = false;
this.flags = -1;
Clazz_instantialize(this, arguments);}, JS.SmilesSearch, "SmilesTarget", JU.JmolMolecule);
Clazz_prepareFields (c$, function(){
this.bsAromatic =  new JU.BS();
this.bsAromatic5 =  new JU.BS();
this.bsAromatic6 =  new JU.BS();
});
Clazz_defineMethod(c$, "hasRingData", 
function(flags){
if (flags != this.flags) {
this.flags = flags;
this.$hasRingData = false;
}var ret = this.$hasRingData;
this.$hasRingData = true;
return ret;
}, "~N");
Clazz_defineMethod(c$, "setAtoms", 
function(atoms, ac, bs){
this.$hasRingData = false;
this.nodes = atoms;
this.ac = ac;
this.selectedAtomCount = (bs == null ? ac : bs.cardinality());
if (bs == null) {
bs = JU.BS.newN(ac);
bs.setBits(0, ac);
}this.bsSelected = bs;
}, "~A,~N,JU.BS");
Clazz_defineMethod(c$, "checkAromaticDefined", 
function(){
JS.SmilesAromatic.checkAromaticDefined(this.nodes, this.bsSelected, this.bsAromatic);
});
Clazz_defineMethod(c$, "getBSAromaticRings", 
function(){
if (this.bsAromaticRings == null) {
this.bsAromaticRings =  new JU.BS();
if (this.ringSets != null && this.bsAromatic != null) {
for (var i = this.ringSets.size(); --i >= 0; ) {
var bsRing = this.ringSets.get(i).clone();
bsRing.andNot(this.bsAromatic);
if (bsRing.isEmpty()) this.bsAromaticRings.set(i);
}
}}return this.bsAromaticRings;
});
Clazz_defineMethod(c$, "setRingData", 
function(strictness, needRingData, ringDataMax){
if (ringDataMax < 0) ringDataMax = 8;
if (strictness > 0 && ringDataMax < 6) ringDataMax = 6;
if (needRingData) {
this.ringCounts =  Clazz_newIntArray (this.ac, 0);
this.ringConnections =  Clazz_newIntArray (this.ac, 0);
this.ringData =  new Array(ringDataMax + 1);
}this.ringSets =  new JU.Lst();
return this.ringDataMax = ringDataMax;
}, "~N,~B,~N");
Clazz_defineMethod(c$, "finalizeAromatic", 
function(lstAromatic){
this.bsAromatic5.clearAll();
this.bsAromatic6.clearAll();
for (var i = lstAromatic.size(); --i >= 0; ) {
var bs = lstAromatic.get(i);
bs.and(this.bsAromatic);
switch (bs.cardinality()) {
case 5:
this.bsAromatic5.or(bs);
break;
case 6:
this.bsAromatic6.or(bs);
break;
}
}
}, "JU.Lst");
Clazz_defineMethod(c$, "finalizeRingData", 
function(){
for (var i = this.bsSelected.nextSetBit(0); i >= 0; i = this.bsSelected.nextSetBit(i + 1)) {
var atom = this.nodes[i];
var nb = atom.getBondCount();
for (var k = nb; --k >= 0; ) {
if (this.ringCounts[atom.getBondedAtomIndex(k)] > 0) this.ringConnections[i]++;
}
}
});
Clazz_defineMethod(c$, "hasDoubleBonds", 
function(){
for (var i = 0; i < this.nodes.length; i++) if (this.bsSelected == null || this.bsSelected.get(i)) {
var n = this.nodes[i];
if (n.getElementNumber() == 1) {
continue;
}var nb = n.getBondCount();
var edges = n.getEdges();
for (var j = 0; j < nb; j++) {
if (edges[j].isCovalent() && edges[j].getBondType() != 1) return true;
}
}
return false;
});
/*eoif3*/})();
});
;//5.0.1-v7 Tue Feb 10 12:29:49 CST 2026
Clazz_declarePackage("JS");
Clazz_load(["java.util.Hashtable", "JU.BS", "JS.VTemp"], "JS.SmilesGenerator", ["JU.AU", "$.Lst", "$.SB", "JS.InvalidSmilesException", "$.SmilesAtom", "$.SmilesBond", "$.SmilesParser", "$.SmilesSearch", "$.SmilesStereo", "JU.BSUtil", "$.Elements", "$.JmolMolecule", "$.Logger"], function(){
var c$ = Clazz_decorateAsClass(function(){
this.MODE_COMP_ALLOW_BIO = 1;
this.MODE_COMP_ALLOW_OUTSIDE = 2;
this.MODE_COMP_FORCE_BRACKETS = 4;
this.ptAtom = 0;
this.ptSp2Atom0 = 0;
this.atoms = null;
this.ac = 0;
this.bsSelected = null;
this.bsAromatic = null;
this.flags = 0;
this.explicitHydrogen = 0;
this.ringSets = null;
this.vTemp = null;
this.nPairs = 0;
this.nPairsMax = 0;
this.bsBondsUp = null;
this.bsBondsDn = null;
this.bsToDo = null;
this.bsIgnoreHydrogen =  new JU.BS();
this.prevAtom = null;
this.prevSp2Atoms = null;
this.alleneStereo = null;
this.htRingsSequence = null;
this.htRings = null;
this.bsRingKeys = null;
this.bsIncludingH = null;
this.topologyOnly = false;
this.getAromatic = true;
this.addAtomComment = false;
this.noBioComment = false;
this.aromaticDouble = false;
this.noStereo = false;
this.openSMILES = false;
this.polySmilesCenter = null;
this.smilesStereo = null;
this.isPolyhedral = false;
this.aromaticRings = null;
this.sm = null;
this.iHypervalent = 0;
this.is2D = false;
this.haveSmilesAtoms = false;
this.noBranches = false;
this.allComponents = false;
this.allowBioResidues = false;
this.allowConnectionsToOutsideWorld = false;
this.forceBrackets = false;
this.bsEnds = null;
this.atemp = null;
this.chainCheck = 0;
Clazz_instantialize(this, arguments);}, JS, "SmilesGenerator", null);
Clazz_prepareFields (c$, function(){
this.vTemp =  new JS.VTemp();
this.bsBondsUp =  new JU.BS();
this.bsBondsDn =  new JU.BS();
this.htRingsSequence =  new java.util.Hashtable();
this.htRings =  new java.util.Hashtable();
this.bsRingKeys =  new JU.BS();
this.bsEnds =  new JU.BS();
});
Clazz_defineMethod(c$, "getSmiles", 
function(sm, atoms, ac, bsSelected, comment, flags){
var ipt = bsSelected.nextSetBit(0);
if (ipt < 0) return "";
this.haveSmilesAtoms = (Clazz_instanceOf(atoms[ipt],"JS.SmilesAtom") && (atoms[ipt]).definesStereo());
this.sm = sm;
this.flags = flags;
this.atoms = atoms;
this.ac = ac;
bsSelected = JU.BSUtil.copy(bsSelected);
this.bsSelected = JU.BS.copy(bsSelected);
this.flags = flags = JS.SmilesSearch.addFlags(flags, comment == null ? "" : comment.toUpperCase());
if ((flags & 1048576) == 1048576) return this.getBioSmiles(bsSelected, comment, flags);
this.openSMILES = ((flags & 5) == 5);
this.addAtomComment = ((flags & 131072) == 131072);
this.aromaticDouble = ((flags & 512) == 512);
this.explicitHydrogen = ((flags & 8192) == 8192 ? 8192 : (flags & 4096) == 4096 ? 4096 : 0);
if (this.explicitHydrogen == 8192) {
var bsHa =  new JU.BS();
for (var i = bsSelected.nextSetBit(0); i >= 0; i = bsSelected.nextSetBit(i + 1)) {
var a = atoms[i];
if (a.getCovalentHydrogenCount() == 3 && (a.getCovalentBondCount() == 4)) {
var doIgnore = true;
bsHa.clearAll();
for (var j = a.getBondCount(); --j >= 0; ) {
var aj = a.getBondedAtomIndex(j);
if (atoms[aj].getElementNumber() == 1) {
doIgnore = (atoms[aj].getElementNumber() == 1);
if (doIgnore) bsHa.set(aj);
 else break;
}if (doIgnore) {
this.bsIgnoreHydrogen.set(i);
bsSelected.andNot(bsHa);
}}
}}
}this.topologyOnly = ((flags & 16384) == 16384);
this.getAromatic = !((flags & 16) == 16);
this.noStereo = ((flags & 32) == 32);
this.isPolyhedral = ((flags & 65536) == 65536);
this.is2D = ((flags & 134217728) == 134217728);
this.noBranches = false;
this.allComponents = ((flags & 32768) == 32768);
return this.getSmilesComponent(atoms[ipt], bsSelected, 1);
}, "JS.SmilesMatcher,~A,~N,JU.BS,~S,~N");
Clazz_defineMethod(c$, "getBioSmiles", 
function(bsSelected, comment, flags){
this.addAtomComment = ((flags & 131072) == 131072);
var allowUnmatchedRings = ((flags & 3145728) == 3145728);
var noBioComments = ((flags & 34603008) == 34603008);
var crosslinkCovalent = ((flags & 5242880) == 5242880);
var crosslinkHBonds = ((flags & 9437184) == 9437184);
var addCrosslinks = (crosslinkCovalent || crosslinkHBonds);
var sb =  new JU.SB();
var bs = bsSelected;
if (comment != null && !this.noBioComment) sb.append("//* Jmol bioSMILES ").append(comment.$replace('*', '_')).append(" *//");
var end = (this.noBioComment ? "" : "\n");
var bsIgnore =  new JU.BS();
var lastComponent = null;
var groupString = "";
var s;
var vLinks =  new JU.Lst();
try {
var len = 0;
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
var a = this.atoms[i];
var ch = a.getGroup1('?');
var bioStructureName = a.getBioStructureTypeName();
var unknown = (ch === ch.toLowerCase());
if (end != null) {
if (sb.length() > 0) sb.append(end);
end = null;
len = 0;
if (bioStructureName.length > 0) {
var id = a.getChainID();
if (id != 0 && !noBioComments) {
s = "//* chain " + a.getChainIDStr() + " " + bioStructureName + " " + a.getResno() + " *// ";
len = s.length;
sb.append(s);
}len++;
sb.append("~").appendC(bioStructureName.toLowerCase().charAt(0)).append("~");
} else {
s = this.getSmilesComponent(a, bs, 6);
if (s.equals(lastComponent)) {
end = "";
continue;
}lastComponent = s;
var groupName = a.getGroup3(true);
var key;
if (noBioComments) {
key = "/" + s + "/";
} else {
if (groupName != null) {
s = "//* " + groupName + " *//" + s;
}key = s + "//";
}if (groupString.indexOf(key) >= 0) {
end = "";
continue;
}groupString += key;
sb.append(s);
end = (noBioComments ? "." : ".\n");
continue;
}}if (len >= 75 && !noBioComments) {
sb.append("\n  ");
len = 2;
}if (this.addAtomComment) sb.append("\n//* [" + a.getGroup3(false) + "#" + a.getResno() + "] *//\t");
if (unknown) {
this.addBracketedBioName(sb, a, bioStructureName.length > 0 ? ".0" : null, false);
} else {
sb.append(ch);
}len++;
if (addCrosslinks) {
a.getCrossLinkVector(vLinks, crosslinkCovalent, crosslinkHBonds);
for (var j = 0; j < vLinks.size(); j += 3) {
sb.append(":");
s = this.getRingCache(vLinks.get(j).intValue(), vLinks.get(j + 1).intValue(), this.htRingsSequence);
sb.append(s);
len += 1 + s.length;
}
vLinks.clear();
}a.getGroupBits(bsIgnore);
bs.andNot(bsIgnore);
var i2 = a.getOffsetResidueAtom("\0", 1);
if (i2 < 0 || !bs.get(i2)) {
if (!noBioComments) sb.append(" //* ").appendI(a.getResno()).append(" *//");
if (i2 < 0 && (i2 = bs.nextSetBit(i + 1)) < 0) break;
if (len > 0) end = (noBioComments ? "." : ".\n");
}i = i2 - 1;
}
} catch (e) {
if (Clazz_exceptionOf(e, Exception)){
throw  new JS.InvalidSmilesException("//* error: " + e.getMessage() + " *//");
} else {
throw e;
}
}
if (!allowUnmatchedRings && !this.htRingsSequence.isEmpty()) {
this.dumpRingKeys(sb, this.htRingsSequence);
throw  new JS.InvalidSmilesException("//* ?ring error? *//");
}s = sb.toString();
if (s.endsWith(".\n")) s = s.substring(0, s.length - 2);
 else if (noBioComments && s.endsWith(".")) s = s.substring(0, s.length - 1);
return s;
}, "JU.BS,~S,~N");
Clazz_defineMethod(c$, "addBracketedBioName", 
function(sb, atom, atomName, addComment){
sb.append("[");
if (atomName != null) {
var chain = atom.getChainIDStr();
sb.append(atom.getGroup3(false));
if (!atomName.equals(".0")) sb.append(atomName).append("#").appendI(atom.getElementNumber());
if (addComment) {
sb.append("//* ").appendI(atom.getResno());
if (chain.length > 0) sb.append(":").append(chain);
sb.append(" *//");
}} else {
sb.append(JU.Elements.elementNameFromNumber(atom.getElementNumber()));
}sb.append("]");
}, "JU.SB,JU.Node,~S,~B");
Clazz_defineMethod(c$, "getSmilesComponent", 
function(atom, bs, mode){
var ret = "";
this.allowBioResidues = ((mode & 1) != 0);
this.allowConnectionsToOutsideWorld = ((mode & 2) != 0);
this.forceBrackets = ((mode & 4) != 0);
while (true) {
if (atom == null) atom = this.atoms[bs.nextSetBit(0)];
atom = this.checkFirstAtom(atom);
this.bsSelected = JU.JmolMolecule.getBranchBitSet(this.atoms, atom.getIndex(), JU.BSUtil.copy(bs), null, -1, true, this.allowBioResidues);
bs.andNot(this.bsSelected);
this.iHypervalent = -1;
for (var i = this.bsSelected.nextSetBit(0); i >= 0 && this.iHypervalent < 0; i = this.bsSelected.nextSetBit(i + 1)) {
if (this.atoms[i].getCovalentBondCount() > 4 || this.isPolyhedral) {
this.iHypervalent = i;
}}
this.bsIncludingH = JU.BSUtil.copy(this.bsSelected);
if (this.explicitHydrogen == 0) {
for (var j = this.bsSelected.nextSetBit(0); j >= 0; j = this.bsSelected.nextSetBit(j + 1)) {
var a = this.atoms[j];
if (a.getAtomicAndIsotopeNumber() == 1 && a.getBondCount() > 0 && a.getBondedAtomIndex(0) != this.iHypervalent && !this.isExplicitOnly(this.atoms[a.getBondedAtomIndex(0)])) this.bsSelected.clear(j);
}
}this.bsAromatic =  new JU.BS();
if (!this.topologyOnly && this.bsSelected.cardinality() > 2) {
this.generateRingData();
this.setBondDirections();
}this.bsToDo = JU.BSUtil.copy(this.bsSelected);
var sb =  new JU.SB();
for (var i = this.bsToDo.nextSetBit(0); i >= 0; i = this.bsToDo.nextSetBit(i + 1)) {
if (this.atoms[i].getCovalentBondCount() > 4 || this.isPolyhedral || this.noBranches) {
if (atom == null) sb.append(".");
this.getSmilesAt(sb, this.atoms[i], false, false);
atom = null;
}}
if (atom != null) {
while ((atom = this.getSmilesAt(sb, atom, true, false)) != null) {
}
}while (!this.bsToDo.isEmpty() || !this.htRings.isEmpty()) {
var e = this.htRings.values().iterator();
if (e.hasNext()) {
atom = this.atoms[(e.next()[1]).intValue()];
if (!this.bsToDo.get(atom.getIndex())) break;
} else {
atom = this.atoms[this.bsToDo.nextSetBit(0)];
}sb.append(".");
this.prevSp2Atoms = this.alleneStereo = null;
this.prevAtom = null;
while ((atom = this.getSmilesAt(sb, atom, true, false)) != null) {
}
}
if (!this.htRings.isEmpty()) {
this.dumpRingKeys(sb, this.htRings);
throw  new JS.InvalidSmilesException("//* ?ring error? *//\n" + sb);
}var s = sb.toString();
if (s.indexOf("^-") >= 0) {
var s0 = s;
try {
var keys = this.sm.getAtropisomerKeys(s, this.atoms, this.ac, this.bsSelected, this.bsAromatic, this.flags);
for (var i = 1; i < keys.length; ) {
var pt = s.indexOf("^-");
if (pt < 0) break;
s = s.substring(0, pt + 1) + keys.substring(i, i + 3).trim() + s.substring(pt + 1);
i += 3;
}
} catch (e) {
if (Clazz_exceptionOf(e, Exception)){
e.printStackTrace();
s = s0;
} else {
throw e;
}
}
}ret += s;
var ipt = bs.nextSetBit(0);
if (ipt < 0 || !this.allComponents) break;
ret += ".";
atom = null;
}
return ret;
}, "JU.Node,JU.BS,~N");
Clazz_defineMethod(c$, "checkFirstAtom", 
function(atom){
if (this.explicitHydrogen == 0 && atom.getAtomicAndIsotopeNumber() == 1 && atom.getEdges().length > 0) atom = this.atoms[atom.getBondedAtomIndex(0)];
var a = atom;
var aprev = null;
while (true) {
if (a.getCovalentBondCount() != 2) break;
var bonds = a.getEdges();
if (bonds[0].getBondType() != 2 || bonds[1].getBondType() != 2) break;
var anext = bonds[0].getOtherNode(a);
if (anext === aprev) anext = bonds[1].getOtherNode(a);
aprev = a;
a = anext;
}
return (a == null ? atom : a);
}, "JU.Node");
Clazz_defineMethod(c$, "generateRingData", 
function(){
var search = JS.SmilesParser.newSearch("[r500]", true, true);
search.target.setAtoms(this.atoms, this.ac, this.bsSelected);
search.setFlags(this.flags);
if (!search.needRingData && search.target.hasDoubleBonds()) search.needRingData = true;
search.ringDataMax = 7;
search.flags = this.flags;
var vRings = JU.AU.createArrayOfArrayList(4);
search.setRingData(null, vRings, true);
this.bsAromatic = search.target.bsAromatic;
this.ringSets = search.target.ringSets;
this.aromaticRings = vRings[3];
});
Clazz_defineMethod(c$, "getBondStereochemistry", 
function(bond, atomFrom){
if (bond == null) return '\0';
var i = bond.index;
var isFirst = (atomFrom == null || bond.getAtomIndex1() == atomFrom.getIndex());
return (this.bsBondsUp.get(i) ? (isFirst ? '/' : '\\') : this.bsBondsDn.get(i) ? (isFirst ? '\\' : '/') : '\0');
}, "JU.Edge,JU.SimpleNode");
Clazz_defineMethod(c$, "setBondDirections", 
function(){
var bsDone =  new JU.BS();
var edges =  Clazz_newArray(2, 3, null);
for (var i = this.bsSelected.nextSetBit(0); i >= 0; i = this.bsSelected.nextSetBit(i + 1)) {
var atom1 = this.atoms[i];
var bonds = atom1.getEdges();
for (var k = 0; k < bonds.length; k++) {
var bond = bonds[k];
var index = bond.index;
var atom2;
if (bsDone.get(index) || bond.getCovalentOrder() != 2 || JS.SmilesSearch.isRingBond(this.ringSets, null, i, (atom2 = bond.getOtherNode(atom1)).getIndex())) continue;
bsDone.set(index);
var nCumulene = 0;
var a10 = atom1;
while (atom2.getCovalentBondCount() == 2 && atom2.getValence() == 4) {
var e2 = atom2.getEdges();
var e = e2[e2[0].getOtherNode(atom2) === a10 ? 1 : 0];
bsDone.set(e.index);
a10 = atom2;
atom2 = e.getOtherNode(atom2);
nCumulene++;
}
if (nCumulene % 2 == 1) continue;
var b0 = null;
var a0 = null;
var i0 = 0;
var atom12 =  Clazz_newArray(-1, [atom1, atom2]);
var edgeCount = 1;
for (var j = 0; j < 2 && edgeCount > 0 && edgeCount < 3; j++) {
edgeCount = 0;
var atomA = atom12[j];
var bb = (atomA).getEdges();
var explicitH = this.explicitHydrogen > 0 || this.isExplicitOnly(atomA);
for (var b = 0; b < bb.length; b++) {
var other;
if (bb[b].getCovalentOrder() != 1 || !explicitH && (other = bb[b].getOtherNode(atomA)).getElementNumber() == 1 && other.getIsotopeNumber() == 0) continue;
edges[j][edgeCount++] = bb[b];
if (this.getBondStereochemistry(bb[b], atomA) != '\0') {
b0 = bb[b];
i0 = j;
}}
}
if (edgeCount == 3 || edgeCount == 0) continue;
if (b0 == null) {
i0 = 0;
b0 = edges[i0][0];
this.bsBondsUp.set(b0.index);
}var aA = atom12[i0];
var c0 = this.getBondStereochemistry(b0, aA);
a0 = b0.getOtherNode(aA);
if (a0 == null) continue;
for (var j = 0; j < 2; j++) {
var aB = atom12[j];
for (var jj = 0; jj < 2; jj++) {
var b1 = edges[j][jj];
if (b1 == null || b1 === b0) continue;
var bi = b1.index;
var a1 = b1.getOtherNode(aB);
if (a1 == null) continue;
var c1 = this.getBondStereochemistry(b1, aB);
var isOpposite;
if (this.haveSmilesAtoms) {
var isop = (a0).isStereoOpposite(a1.getIndex(), aA.getIndex(), aB.getIndex());
if (isop == null) {
if (JU.Logger.debugging) JU.Logger.debug("SmilesGenerator could not find stereo for " + a0 + "/" + a1);
continue;
}isOpposite = isop.booleanValue();
} else {
isOpposite = JS.SmilesStereo.isDiaxial(aA, aB, a0, a1, this.vTemp, 0);
}if (c1 == '\0' || (c1 != c0) == isOpposite) {
var isUp = (c0 == '\\' && isOpposite || c0 == '/' && !isOpposite);
if (isUp == (b1.getAtomIndex1() != a1.getIndex())) {
this.bsBondsUp.set(bi);
} else {
this.bsBondsDn.set(bi);
}} else {
this.bsBondsUp.clear(bi);
this.bsBondsDn.clear(bi);
JU.Logger.error("BOND STEREOCHEMISTRY PARITY ERROR-stereochemistry for bond " + bi + "");
}if (JU.Logger.debugging) JU.Logger.debug(this.getBondStereochemistry(b0, aA) + " " + a0.getIndex() + " " + a1.getIndex() + " " + this.getBondStereochemistry(b1, aB));
}
}
}
}
});
Clazz_defineMethod(c$, "getSmilesAt", 
function(sb, atom, allowBranches, isBranch){
var atomIndex = atom.getIndex();
if (!this.bsToDo.get(atomIndex)) return null;
var pt = sb.length() - 1;
this.ptAtom++;
this.bsToDo.clear(atomIndex);
var includeHs = (atomIndex == this.iHypervalent || this.explicitHydrogen != 0 && !this.bsIgnoreHydrogen.get(atomIndex));
var explicitHs = this.isExplicitOnly(atom);
var isAromatic = this.bsAromatic.get(atomIndex);
var isExtension = (!this.bsSelected.get(atomIndex));
var prevIndex = (this.prevAtom == null ? -1 : this.prevAtom.getIndex());
var sp2Atoms = this.prevSp2Atoms;
var havePreviousSp2Atoms = (sp2Atoms != null);
var atomicNumber = atom.getElementNumber();
var nH = 0;
var prevStereo = this.alleneStereo;
this.alleneStereo = null;
var v =  new JU.Lst();
var bondNext = null;
var bondPrev = null;
var bonds = atom.getEdges();
if (!isBranch && this.polySmilesCenter != null) {
allowBranches = false;
this.sortPolyBonds(atom, this.prevAtom, this.polySmilesCenter);
}var aH = null;
var stereoFlag = (isAromatic ? 10 : 0);
if (JU.Logger.debugging) JU.Logger.debug(sb.toString());
if (bonds != null) {
for (var i = 0, nb = bonds.length; i < nb; i++) {
var bond = bonds[i];
if (!bond.isCovalent()) continue;
if (bond.order == 1057) {
stereoFlag = 10;
}var atom1 = bonds[i].getOtherNode(atom);
var index1 = atom1.getIndex();
if (index1 == prevIndex) {
bondPrev = bonds[i];
continue;
}var isH = !includeHs && !explicitHs && (atom1.getElementNumber() == 1 && atom1.getIsotopeNumber() <= 0);
if (!this.bsIncludingH.get(index1)) {
if (isH || !this.allowConnectionsToOutsideWorld || !this.bsSelected.get(atomIndex)) continue;
this.bsToDo.set(index1);
}if (isH) {
aH = atom1;
nH++;
if (nH > 1) stereoFlag = 10;
} else {
v.addLast(bonds[i]);
}}
}if (nH > 1) sp2Atoms = null;
var nSp2Atoms = (sp2Atoms != null ? 2 : 0);
if (sp2Atoms == null && !isAromatic && nH <= 1) sp2Atoms =  new Array(5);
var strPrev = null;
if (bondPrev != null) {
strPrev = this.getBondOrder(bondPrev, atomIndex, prevIndex, isAromatic);
if (sp2Atoms != null && !havePreviousSp2Atoms) {
sp2Atoms[nSp2Atoms++] = this.prevAtom;
}}if (sp2Atoms != null && !havePreviousSp2Atoms) {
this.ptSp2Atom0 = this.ptAtom;
}if (sp2Atoms != null && nH == 1) sp2Atoms[nSp2Atoms++] = aH;
var nMax = 0;
var bsBranches =  new JU.BS();
var nBonds = v.size();
if (allowBranches) {
for (var i = 0; i < nBonds; i++) {
var bond = v.get(i);
var a = bond.getOtherNode(atom);
var n = a.getCovalentBondCount() - (includeHs || this.isExplicitOnly(a) ? 0 : (a).getCovalentHydrogenCount());
var order = bond.getCovalentOrder();
var isEndPoint = this.htRings.containsKey(JS.SmilesGenerator.getRingKey(a.getIndex(), atomIndex));
if (isEndPoint) continue;
var check = (bondNext != null || i < nBonds - 1);
if (n == 1 && check) {
bsBranches.set(bond.index);
} else if ((order > 1 || n > nMax)) {
nMax = (order > 1 ? 1000 + order : n);
bondNext = bond;
}}
}var atomNext = (bondNext == null ? null : bondNext.getOtherNode(atom));
var orderNext = (bondNext == null ? 0 : bondNext.getCovalentOrder());
var stereo =  new Array(7);
if (stereoFlag < 7 && bondPrev != null) {
if (havePreviousSp2Atoms && bondPrev.getCovalentOrder() == 2 && orderNext == 2 && sp2Atoms[1] != null) {
stereo[stereoFlag++] = sp2Atoms[0];
stereo[stereoFlag++] = sp2Atoms[1];
} else {
stereo[stereoFlag++] = this.prevAtom;
}}if (stereoFlag < 7 && nH == 1) stereo[stereoFlag++] = aH;
var deferStereo = false;
var chBond = this.getBondStereochemistry(bondPrev, this.prevAtom);
if (strPrev != null || chBond != '\0') {
if (chBond != '\0') strPrev = "" + chBond;
sb.append(strPrev);
}var stereoFlag0 = stereoFlag;
var nSp2Atoms0 = nSp2Atoms;
var sbBranches =  new JU.SB();
var vBranches =  new JU.Lst();
for (var i = 0; i < v.size(); i++) {
var bond = v.get(i);
if (!bsBranches.get(bond.index)) continue;
var a = bond.getOtherNode(atom);
var s2 =  new JU.SB();
this.prevAtom = atom;
this.prevSp2Atoms = this.alleneStereo = null;
var bond0t = bondNext;
var ptSp2Atom0t = this.ptSp2Atom0;
var ptAtomt = this.ptAtom;
this.getSmilesAt(s2, a, allowBranches, true);
bondNext = bond0t;
this.ptAtom = ptAtomt;
this.ptSp2Atom0 = ptSp2Atom0t;
var branch = s2.toString();
v.removeItemAt(i--);
if (bondNext == null) vBranches.addLast(branch);
 else sbBranches.append("(").append(branch).append(")");
if (stereoFlag < 7) stereo[stereoFlag++] = a;
if (sp2Atoms != null && nSp2Atoms < 5) sp2Atoms[nSp2Atoms++] = a;
}
var sbRings =  new JU.SB();
var stereoFlag1 = stereoFlag;
var nSp2Atoms1 = nSp2Atoms;
var atat = null;
if (!allowBranches && !this.noStereo && this.polySmilesCenter == null && (v.size() == 5 || v.size() == 6)) {
atat = this.sortInorganic(atom, v, this.vTemp);
}for (var i = 0; i < v.size(); i++) {
var bond = v.get(i);
if (bond === bondNext) continue;
var a = bond.getOtherNode(atom);
var ia = a.getIndex();
strPrev = this.getBondOrder(bond, atomIndex, ia, isAromatic);
chBond = this.getBondStereochemistry(bond, atom);
if (!deferStereo && chBond != '\0') {
strPrev = "" + chBond;
}sbRings.append(strPrev);
sbRings.append(this.getRingCache(atomIndex, ia, this.htRings));
if (stereoFlag < 7) stereo[stereoFlag++] = a;
if (sp2Atoms != null && nSp2Atoms < 5) sp2Atoms[nSp2Atoms++] = a;
}
if (stereoFlag0 != stereoFlag1 && stereoFlag1 != stereoFlag) this.swapArray(stereo, stereoFlag0, stereoFlag1, stereoFlag);
if (nSp2Atoms0 != nSp2Atoms1 && nSp2Atoms1 != nSp2Atoms) this.swapArray(sp2Atoms, nSp2Atoms0, nSp2Atoms1, nSp2Atoms);
if (havePreviousSp2Atoms && stereoFlag == 2 && orderNext == 2) {
var nc = (this.ptAtom - this.ptSp2Atom0);
var nb = atomNext.getCovalentBondCount();
var lastIsN = (atomNext.getElementNumber() == 7);
if (nc % 2 == 0) {
stereoFlag = 8;
} else {
if (nb == 3 || nb == 2 && lastIsN) {
if (!includeHs && sb.charAt(pt) != ')' && (stereo[0]).getAtomicAndIsotopeNumber() == 1) {
var s0 = stereo[0];
stereo[0] = stereo[1];
stereo[1] = s0;
}bonds = atomNext.getEdges();
for (var k = 0; k < bonds.length; k++) {
var index = atomNext.getBondedAtomIndex(k);
if (bonds[k].isCovalent() && index != atomIndex) stereo[stereoFlag++] = this.atoms[index];
}
if (nb == 2) stereo[stereoFlag++] = atomNext;
if (stereoFlag == 4) {
this.alleneStereo = stereo;
}}}nSp2Atoms = 0;
} else if (atomNext != null && stereoFlag < 7) {
stereo[stereoFlag++] = atomNext;
}if (prevStereo != null) {
if (prevStereo[3] !== stereo[2]) {
var ptat = sb.lastIndexOf("@]=");
if (ptat > 0) {
var trail = sb.substring(ptat);
sb.setLength(sb.charAt(ptat - 1) == '@' ? ptat - 1 : ptat + 1);
sb.append(trail);
}}prevStereo = null;
}if (this.haveSmilesAtoms && atat == null && (stereoFlag == 4)) {
atat = (atom).getStereoAtAt(stereo);
}var charge = atom.getFormalCharge();
var isotope = atom.getIsotopeNumber();
var valence = atom.getValence();
var osclass = (this.openSMILES ? (atom).getFloatProperty("property_atomclass") : NaN);
if (osclass == 0) osclass = NaN;
var atomName = atom.getAtomName();
var groupType = (atom).getBioStructureTypeName();
if (this.addAtomComment) sb.append("\n//* " + atom.toString() + " *//\t");
if (this.topologyOnly) {
sb.append("*");
} else if (isExtension && groupType.length != 0 && atomName.length != 0) {
this.addBracketedBioName(sb, atom, "." + atomName, false);
} else {
sb.append(JS.SmilesAtom.getAtomLabel(atomicNumber, isotope, (this.forceBrackets ? -1 : valence), charge, osclass, nH, isAromatic, atat != null ? atat : this.noStereo ? null : this.checkStereoPairs(atom, this.alleneStereo == null ? atomIndex : -1, stereo, stereoFlag, prevIndex == -1), this.is2D));
}sb.appendSB(sbRings);
if (bondNext != null) {
sb.appendSB(sbBranches);
} else {
var n = vBranches.size() - 1;
if (n >= 0) {
for (var i = 0; i < n; i++) sb.append("(").append(vBranches.get(i)).append(")");

sb.append(vBranches.get(n));
}return null;
}if (sp2Atoms != null && orderNext == 2 && (nSp2Atoms == 1 || nSp2Atoms == 2)) {
if (sp2Atoms[0] == null) sp2Atoms[0] = atom;
if (sp2Atoms[1] == null) sp2Atoms[1] = atom;
} else {
sp2Atoms = null;
nSp2Atoms = 0;
}this.prevSp2Atoms = sp2Atoms;
this.prevAtom = atom;
return atomNext;
}, "JU.SB,JU.SimpleNode,~B,~B");
Clazz_defineMethod(c$, "isExplicitOnly", 
function(atom){
return (atom.getElementNumber() == 7 && atom.getCovalentBondCount() == 2 || atom.getElementNumber() == 6 && atom.getIsotopeNumber() == 17);
}, "JU.SimpleNode");
Clazz_defineMethod(c$, "swapArray", 
function(a, i0, i1, i2){
var n = i1 - i0;
if (this.atemp == null || this.atemp.length < n) this.atemp =  new Array(n);
for (var p = n, i = i1; p > 0; ) this.atemp[--p] = a[--i];

for (var i = i1; i < i2; i++) a[i - n] = a[i];

for (var p = n, i = i2; p > 0; ) a[--i] = this.atemp[--p];

}, "~A,~N,~N,~N");
Clazz_defineMethod(c$, "getBondOrder", 
function(bondPrev, atomIndex, prevIndex, isAromatic){
if (this.topologyOnly) return "";
if ((bondPrev.order & 65537) == 65537) {
return "^-";
}var border = Math.max(bondPrev.isPartial() ? 1 : 0, bondPrev.getCovalentOrder());
return (!isAromatic || !this.bsAromatic.get(prevIndex) ? JS.SmilesBond.getBondOrderString(border) : border == 1 && !this.isSameAromaticRing(atomIndex, prevIndex) ? "-" : this.aromaticDouble && (border == 2 || border == 514) ? "=" : "");
}, "JU.Edge,~N,~N,~B");
Clazz_defineMethod(c$, "isSameAromaticRing", 
function(a1, a2){
var bs;
for (var i = this.aromaticRings.size(); --i >= 0; ) if ((bs = this.aromaticRings.get(i)).get(a1) && bs.get(a2)) return true;

return false;
}, "~N,~N");
Clazz_defineMethod(c$, "sortPolyBonds", 
function(atom, refAtom, center){
if (this.smilesStereo == null) try {
this.smilesStereo = JS.SmilesStereo.newStereo(null);
} catch (e) {
if (Clazz_exceptionOf(e,"JS.InvalidSmilesException")){
} else {
throw e;
}
}
this.smilesStereo.sortPolyBondsByStereo(atom, refAtom, center, atom.getEdges(), this.vTemp.vA);
}, "JU.SimpleNode,JU.SimpleNode,JU.P3");
Clazz_defineMethod(c$, "sortInorganic", 
function(atom, v, vTemp){
var atomIndex = atom.getIndex();
var n = v.size();
var axialPairs =  new JU.Lst();
var bonds =  new JU.Lst();
var a1;
var a2;
var a01 = null;
var a02 = null;
var bond1;
var bond2;
var bsDone =  new JU.BS();
var pair0 = null;
var stereo =  new Array(6);
var isOK = true;
var s = "";
var naxial = 0;
for (var i = 0; i < n; i++) {
bond1 = v.get(i);
stereo[0] = a1 = bond1.getOtherNode(atom);
if (i == 0) s = this.addStereoCheck(0, atomIndex, a1, "", null);
 else if (isOK && this.addStereoCheck(0, atomIndex, a1, s, null) != null) isOK = false;
if (bsDone.get(i)) continue;
bsDone.set(i);
var isAxial = false;
for (var j = i + 1; j < n; j++) {
if (bsDone.get(j)) continue;
bond2 = v.get(j);
a2 = bond2.getOtherNode(atom);
if (JS.SmilesStereo.isDiaxial(atom, atom, a1, a2, vTemp, -0.95)) {
switch (++naxial) {
case 1:
a01 = a1;
break;
case 2:
a02 = a1;
break;
case 3:
if (JS.SmilesStereo.getHandedness(a02, a01, a1, atom, vTemp) == 2) {
var b = bond1;
bond1 = bond2;
bond2 = b;
}break;
}
axialPairs.addLast( Clazz_newArray(-1, [bond1, bond2]));
isAxial = true;
bsDone.set(j);
break;
}}
if (!isAxial) bonds.addLast(bond1);
}
var npAxial = axialPairs.size();
if (isOK || n == 6 && npAxial != 3 || n == 5 && npAxial == 0) return "";
pair0 = axialPairs.get(0);
bond1 = pair0[0];
stereo[0] = bond1.getOtherNode(atom);
v.clear();
v.addLast(bond1);
if (npAxial > 1) bonds.addLast(axialPairs.get(1)[0]);
if (npAxial == 3) bonds.addLast(axialPairs.get(2)[0]);
if (npAxial > 1) bonds.addLast(axialPairs.get(1)[1]);
if (npAxial == 3) bonds.addLast(axialPairs.get(2)[1]);
for (var i = 0; i < bonds.size(); i++) {
bond1 = bonds.get(i);
v.addLast(bond1);
stereo[i + 1] = bond1.getOtherNode(atom);
}
v.addLast(pair0[1]);
stereo[n - 1] = pair0[1].getOtherNode(atom);
return JS.SmilesStereo.getStereoFlag(atom, stereo, n, vTemp, this.is2D);
}, "JU.SimpleNode,JU.Lst,JS.VTemp");
Clazz_defineMethod(c$, "checkStereoPairs", 
function(atom, atomIndex, stereo, stereoFlag, isFirst){
if (stereoFlag == 10 || stereoFlag < (this.is2D ? 3 : 4)) return "";
if (this.explicitHydrogen == 0 && atomIndex >= 0 && stereoFlag == 4) {
if (atom.getElementNumber() <= 17) {
var s = "";
for (var i = 0; i < 4; i++) {
if ((s = this.addStereoCheck(0, atomIndex, stereo[i], s, JU.BSUtil.newAndSetBit(atomIndex))) == null) {
return "";
}}
}}if (this.is2D) {
var dir = (stereoFlag == 4 || !isFirst ? 1 : -1);
var bonds = atom.getEdges();
var c = null;
for (var i = atom.getBondCount(); --i >= 0; ) {
var b = bonds[i];
if (atom === b.getAtom(0)) {
switch (b.getBondType()) {
case 1025:
c = JS.SmilesGenerator.setStereoTemp(null, stereo, b.getAtom(1), dir);
break;
case 1041:
c = JS.SmilesGenerator.setStereoTemp(null, stereo, b.getAtom(1), -dir);
break;
}
}}
if (c == null) return "";
if (stereoFlag == 3) {
stereo[stereoFlag++] = JS.SmilesGenerator.setStereoTemp(atom, stereo, c, 0);
}}return JS.SmilesStereo.getStereoFlag(atom, stereo, stereoFlag, this.vTemp, this.is2D);
}, "JU.SimpleNode,~N,~A,~N,~B");
c$.setStereoTemp = Clazz_defineMethod(c$, "setStereoTemp", 
function(atom, stereo, a, z){
var b =  new JS.SmilesAtom();
for (var i = 0; i < 4; i++) {
var isA = (stereo[i] === a);
if (atom == null) {
if (isA) {
var c = a.getXYZ();
b.set(c.x, c.y, z);
return stereo[i] = b;
}} else if (i < 3) {
b.add(stereo[i]);
}}
if (atom == null) return null;
b.scale(-0.33333334);
b.scaleAdd2(2, atom, b);
return b;
}, "JU.SimpleNode,~A,JU.SimpleNode,~N");
Clazz_defineMethod(c$, "addStereoCheck", 
function(level, atomIndex, atom, s, bsDone){
if (bsDone != null) bsDone.set(atomIndex);
var n = (atom).getAtomicAndIsotopeNumber();
if (n == 1 && this.explicitHydrogen == 0) return "H";
var nx = atom.getCovalentBondCount();
var nhcov = (atom).getCovalentHydrogenCount();
var nh = (n == 6 && this.explicitHydrogen != 0 ? nhcov : 0);
if (n == 6 || n == 16 ? nx != 4 : n == 1 || nx > 1) return s + (++this.chainCheck);
var sa = ";" + level + "/" + n + "/" + nh + "/" + nx + (level == 0 ? "," : "_");
if (n == 6 || n == 16) {
switch (nh) {
case 1:
return s + sa + (++this.chainCheck);
case 0:
case 2:
if (bsDone == null) return s;
var edges = (atom).getEdges();
var s2 = "";
var sa2 = "";
var nunique = (nh == 2 ? 0 : 3);
for (var j = atom.getBondCount(); --j >= 0; ) {
var a2 = edges[j].getOtherNode(atom);
var i2 = a2.getIndex();
if (bsDone.get(i2) || !edges[j].isCovalent()) continue;
bsDone.set(i2);
sa2 = this.addStereoCheck(level + 1, atom.getIndex(), a2, "", bsDone.clone());
if (s2.indexOf(sa2) >= 0) nunique--;
s2 += sa2;
}
if (nunique == 3) {
return s + sa + (++this.chainCheck);
}sa = (sa + s2).$replace(',', '_');
if (level > 0) return s + sa;
break;
case 3:
break;
}
}if (s.indexOf(sa) >= 0) {
if (nhcov == 3) {
var ndt = 0;
for (var j = 0; j < nx && ndt < 3; j++) {
var ia = (atom).getBondedAtomIndex(j);
if (ia == atomIndex) continue;
ndt += this.atoms[ia].getAtomicAndIsotopeNumber();
}
if (ndt > 3) return s;
}return null;
}return s + sa;
}, "~N,~N,JU.SimpleNode,~S,JU.BS");
Clazz_defineMethod(c$, "getRingCache", 
function(i0, i1, ht){
var key = JS.SmilesGenerator.getRingKey(i0, i1);
var o = ht.get(key);
var s = (o == null ? null : o[0]);
if (s == null) {
this.bsRingKeys.set(++this.nPairs);
this.nPairsMax = Math.max(this.nPairs, this.nPairsMax);
ht.put(key,  Clazz_newArray(-1, [s = this.getRingPointer(this.nPairs), Integer.$valueOf(i1), Integer.$valueOf(this.nPairs)]));
if (JU.Logger.debugging) JU.Logger.debug("adding for " + i0 + " ring key " + this.nPairs + ": " + key);
} else {
ht.remove(key);
var nPair = (o[2]).intValue();
this.bsRingKeys.clear(nPair);
if (this.bsRingKeys.nextSetBit(0) < 0 && (this.nPairsMax == 2 || this.nPairsMax == 99)) {
this.nPairsMax = this.nPairs = (this.nPairsMax == 99 ? 10 : 0);
}if (JU.Logger.debugging) JU.Logger.debug("using ring key " + key);
}return s;
}, "~N,~N,java.util.Map");
Clazz_defineMethod(c$, "getRingPointer", 
function(i){
return (i < 10 ? "" + i : i < 100 ? "%" + i : "%(" + i + ")");
}, "~N");
Clazz_defineMethod(c$, "dumpRingKeys", 
function(sb, ht){
JU.Logger.info(sb.toString() + "\n\n");
for (var key, $key = ht.keySet().iterator (); $key.hasNext()&& ((key = $key.next ()) || true);) JU.Logger.info("unmatched connection: " + key);

}, "JU.SB,java.util.Map");
c$.getRingKey = Clazz_defineMethod(c$, "getRingKey", 
function(i0, i1){
return Math.min(i0, i1) + "_" + Math.max(i0, i1);
}, "~N,~N");
});
;//5.0.1-v7 Tue Feb 10 12:29:49 CST 2026
Clazz_declarePackage("JS");
Clazz_load(null, "JS.SmilesAromatic", ["java.util.Hashtable", "JU.BS", "$.Lst", "$.Measure", "$.V3", "JS.SmilesRing", "$.SmilesRingSet", "JU.BSUtil", "$.Logger"], function(){
var c$ = Clazz_declareType(JS, "SmilesAromatic", null);
c$.setAromatic = Clazz_defineMethod(c$, "setAromatic", 
function(n, jmolAtoms, bsSelected, vR, bsAromatic, strictness, isOpenSMILES, justCheckBonding, checkExplicit, v, vOK, lstSP2, eCounts, doTestAromatic){
var doCheck = (isOpenSMILES || strictness > 0);
if (!doTestAromatic) {
for (var r = vR.size(); --r >= 0; ) {
var bs = JU.BSUtil.copy(vR.get(r));
bs.and(bsAromatic);
if (bs.cardinality() == n) vOK.addLast(bs);
}
return;
}for (var r = vR.size(); --r >= 0; ) {
var bs = vR.get(r);
var isOK = JS.SmilesAromatic.isSp2Ring(n, jmolAtoms, bsSelected, bs, (justCheckBonding ? 3.4028235E38 : 0.1), checkExplicit, strictness == 0);
if (!isOK) continue;
bsAromatic.or(bs);
if (doCheck) {
var edges =  new JU.Lst();
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
var a = jmolAtoms[i];
var aedges = a.getEdges();
var ai = a.getIndex();
for (var j = aedges.length; --j >= 0; ) {
var a2 = aedges[j].getOtherNode(a);
var a2i = a2.getIndex();
if (a2i > ai && bs.get(a2i)) edges.addLast(aedges[j]);
}
}
switch (JS.SmilesAromatic.checkHueckelAromatic(n, jmolAtoms, bsAromatic, bs, strictness, eCounts)) {
case -1:
continue;
case 0:
isOK = false;
case 1:
if (lstSP2 != null) lstSP2.addLast( new JS.SmilesRing(n, bs, edges, isOK));
if (!isOK) continue;
}
}vOK.addLast(bs);
}
}, "~N,~A,JU.BS,JU.Lst,JU.BS,~N,~B,~B,~B,JS.VTemp,JU.Lst,JU.Lst,~A,~B");
c$.checkAromaticDefined = Clazz_defineMethod(c$, "checkAromaticDefined", 
function(jmolAtoms, bsSelected, bsAromatic){
for (var i = bsSelected.nextSetBit(0); i >= 0; i = bsSelected.nextSetBit(i + 1)) {
var bonds = jmolAtoms[i].getEdges();
for (var j = 0; j < bonds.length; j++) {
switch (bonds[j].getBondType()) {
case 515:
case 514:
case 513:
bsAromatic.set(bonds[j].getAtomIndex1());
bsAromatic.set(bonds[j].getAtomIndex2());
}
}
}
}, "~A,JU.BS,JU.BS");
c$.isSp2Ring = Clazz_defineMethod(c$, "isSp2Ring", 
function(n, atoms, bsSelected, bs, cutoff, checkExplicit, allowSOxide){
if (checkExplicit) {
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) if (atoms[i].getCovalentBondCount() > 3) return false;

} else {
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) if (atoms[i].getCovalentBondCountPlusMissingH() > 3) return false;

}if (cutoff == 3.4028235E38) return true;
if (cutoff <= 0) cutoff = 0.01;
var vNorm = null;
var vTemp = null;
var vMean = null;
var nPoints = bs.cardinality();
var vNorms =  new Array(nPoints * 2);
var nNorms = 0;
var maxDev = (1 - cutoff * 5);
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
var ringAtom = atoms[i];
var bonds = ringAtom.getEdges();
var iSub = -1;
var r1 = -1;
var r2 = -1;
for (var k = bonds.length; --k >= 0; ) {
var iAtom = ringAtom.getBondedAtomIndex(k);
if (!bsSelected.get(iAtom)) continue;
if (!bs.get(iAtom)) {
if (ringAtom.getElementNumber() == 16) {
if (!allowSOxide) return false;
iAtom = -1;
}iSub = iAtom;
} else if (r1 < 0) {
r1 = iAtom;
} else {
r2 = iAtom;
}}
if (vMean == null) {
vMean =  new JU.V3();
vNorm =  new JU.V3();
vTemp =  new JU.V3();
}for (var k = 0, j = i; k < 2; k++) {
JU.Measure.getNormalThroughPoints(atoms[r1], atoms[j], atoms[r2], vNorm, vTemp);
if (!JS.SmilesAromatic.addNormal(vNorm, vMean, maxDev)) return false;
vNorms[nNorms++] = JU.V3.newV(vNorm);
if ((j = iSub) < 0) break;
}
}
return JS.SmilesAromatic.checkStandardDeviation(vNorms, vMean, nNorms, cutoff);
}, "~N,~A,JU.BS,JU.BS,~N,~B,~B");
c$.addNormal = Clazz_defineMethod(c$, "addNormal", 
function(vTemp, vMean, maxDev){
var similarity = vMean.dot(vTemp);
if (similarity != 0 && Math.abs(similarity) < maxDev) return false;
if (similarity < 0) vTemp.scale(-1);
vMean.add(vTemp);
vMean.normalize();
return true;
}, "JU.V3,JU.V3,~N");
c$.checkStandardDeviation = Clazz_defineMethod(c$, "checkStandardDeviation", 
function(vNorms, vMean, n, cutoff){
var sum = 0;
var sum2 = 0;
for (var i = 0; i < n; i++) {
var v = vNorms[i].dot(vMean);
sum += v;
sum2 += (v) * v;
}
sum = Math.sqrt((sum2 - sum * sum / n) / (n - 1));
return (sum < cutoff);
}, "~A,JU.V3,~N,~N");
c$.checkHueckelAromatic = Clazz_defineMethod(c$, "checkHueckelAromatic", 
function(nAtoms, jmolAtoms, bsAromatic, bsRing, strictness, eCounts){
var npi = 0;
var n1 = 0;
for (var i = bsRing.nextSetBit(0); i >= 0 && npi >= 0; i = bsRing.nextSetBit(i + 1)) {
var atom = jmolAtoms[i];
var z = atom.getElementNumber();
var n = atom.getCovalentBondCountPlusMissingH();
n += atom.getValence();
n -= 4;
if (z == 6) {
var fc = atom.getFormalCharge();
if (fc != -2147483648) n += fc;
}var pt = (z >= 5 && z <= 8 ? z - 5 : z == 15 ? 2 : z == 34 ? 3 : z == 33 ? 4 : z == 16 ? 5 : -1);
if (pt >= 0) {
var a = JS.SmilesAromatic.OS_PI_COUNTS[pt];
if (n < 0 || n >= a.length) return -1;
switch (n = a[n]) {
case -2:
return -1;
case -1:
var bonds = atom.getEdges();
n = 0;
for (var j = bonds.length; --j >= 0; ) {
var b = bonds[j];
if (b.getCovalentOrder() != 2) continue;
var het = b.getOtherNode(atom);
n = (het.getElementNumber() == 6 || bsAromatic.get(het.getIndex()) ? 1 : strictness > 0 ? -100 : 0);
break;
}
default:
if (n < 0) return -1;
if (eCounts != null) eCounts[i] = n;
npi += n;
if (n == 1) n1++;
if (JU.Logger.debuggingHigh) JU.Logger.info("atom " + atom + " pi=" + n + " npi=" + npi);
continue;
}
}}
return ((npi - 2) % 4 == 0 && (strictness < 2 || nAtoms == 5 || n1 == 6) ? 1 : 0);
}, "~N,~A,JU.BS,JU.BS,~N,~A");
c$.finalizeAromatic = Clazz_defineMethod(c$, "finalizeAromatic", 
function(jmolAtoms, bsAromatic, lstAromatic, lstSP2, eCounts, isOpenNotStrict, isStrict){
if (isStrict) JS.SmilesAromatic.removeBridgingRings(lstAromatic, lstSP2);
JS.SmilesAromatic.checkFusedRings(lstSP2, eCounts, lstAromatic);
bsAromatic.clearAll();
for (var i = lstAromatic.size(); --i >= 0; ) bsAromatic.or(lstAromatic.get(i));

if (isStrict || isOpenNotStrict) {
for (var i = bsAromatic.nextSetBit(0); i >= 0; i = bsAromatic.nextSetBit(i + 1)) {
var bonds = jmolAtoms[i].getEdges();
var naro = 0;
for (var j = bonds.length; --j >= 0; ) {
var otherAtom = bonds[j].getOtherNode(jmolAtoms[i]);
var order = bonds[j].getCovalentOrder();
var ai2 = otherAtom.getIndex();
var isJAro = bsAromatic.get(ai2);
if (isJAro) {
if (order == 2) {
var isOK = false;
for (var k = lstSP2.size(); --k >= 0; ) {
var r = lstSP2.get(k);
if (r.get(i) && r.get(ai2)) {
isOK = true;
break;
}}
if (!isOK) {
naro = -1;
break;
}}naro++;
} else if (isStrict && otherAtom.getElementNumber() == 6 && order == 2) {
naro = -1;
break;
}}
if (naro < 2) {
bsAromatic.clear(i);
i = -1;
}}
}}, "~A,JU.BS,JU.Lst,JU.Lst,~A,~B,~B");
c$.removeBridgingRings = Clazz_defineMethod(c$, "removeBridgingRings", 
function(lstAromatic, lstSP2){
var bs =  new JU.BS();
var bsBad =  new JU.BS();
var bsBad2 =  new JU.BS();
JS.SmilesAromatic.checkBridges(lstAromatic, bsBad, lstAromatic, bsBad, bs);
JS.SmilesAromatic.checkBridges(lstSP2, bsBad2, lstSP2, bsBad2, bs);
JS.SmilesAromatic.checkBridges(lstAromatic, bsBad, lstSP2, bsBad2, bs);
for (var i = lstAromatic.size(); --i >= 0; ) if (bsBad.get(i)) lstAromatic.removeItemAt(i);

for (var i = lstSP2.size(); --i >= 0; ) if (bsBad2.get(i)) lstSP2.removeItemAt(i);

}, "JU.Lst,JU.Lst");
c$.checkBridges = Clazz_defineMethod(c$, "checkBridges", 
function(lst, bsBad, lst2, bsBad2, bs){
var isSameList = (lst === lst2);
for (var i = lst.size(); --i >= 0; ) {
var bs1 = lst.get(i);
for (var j0 = (isSameList ? i + 1 : 0), j = lst2.size(); --j >= j0; ) {
var bs2 = lst2.get(j);
if (bs2.equals(bs1)) continue;
bs.clearAll();
bs.or(bs1);
bs.and(bs2);
var n = bs.cardinality();
if (n > 2) {
bsBad.set(i);
bsBad2.set(j);
}}
}
}, "JU.Lst,JU.BS,JU.Lst,JU.BS,JU.BS");
c$.checkFusedRings = Clazz_defineMethod(c$, "checkFusedRings", 
function(rings, eCounts, lstAromatic){
var htEdgeMap =  new java.util.Hashtable();
for (var i = rings.size(); --i >= 0; ) {
var r = rings.get(i);
var edges = r.edges;
for (var j = edges.size(); --j >= 0; ) {
var set = JS.SmilesRing.getSetByEdge(edges.get(j), htEdgeMap);
if (set == null || set === r.$set) continue;
if (r.$set != null) set.addSet(r.$set, htEdgeMap);
 else set.addRing(r);
}
(r.$set == null ? r.$set =  new JS.SmilesRingSet() : r.$set).addRing(r);
r.addEdges(htEdgeMap);
}
var set;
var r;
for (var i = rings.size(); --i >= 0; ) {
if ((r = rings.get(i)).isOK || (set = r.$set) == null || set.isEmpty()) continue;
if ((set.getElectronCount(eCounts) % 4) == 2) for (var j = set.size(); --j >= 0; ) if (!(r = set.get(j)).isOK) lstAromatic.addLast(r);

set.clear();
}
}, "JU.Lst,~A,JU.Lst");
c$.OS_PI_COUNTS =  Clazz_newArray(-1, [ Clazz_newIntArray(-1, [-2, 1, 0]),  Clazz_newIntArray(-1, [1, 2, 1, -1]),  Clazz_newIntArray(-1, [2, 1, 2, 1, 1]),  Clazz_newIntArray(-1, [2, 1]),  Clazz_newIntArray(-1, [-2, 1, 2, 1, -2]),  Clazz_newIntArray(-1, [2, 1, 2, 2])]);
});
;//5.0.1-v7 Thu Feb 05 13:38:23 CST 2026
Clazz_declarePackage("JS");
Clazz_load(["JU.BS"], "JS.SmilesRing", null, function(){
var c$ = Clazz_decorateAsClass(function(){
this.$set = null;
this.edges = null;
this.bsEdgesToCheck = null;
this.isOK = false;
this.n = 0;
Clazz_instantialize(this, arguments);}, JS, "SmilesRing", JU.BS);
Clazz_makeConstructor(c$, 
function(n, atoms, edges, isOK){
Clazz_superConstructor (this, JS.SmilesRing, []);
this.or(atoms);
this.edges = edges;
this.isOK = isOK;
this.n = n;
}, "~N,JU.BS,JU.Lst,~B");
Clazz_defineMethod(c$, "addEdges", 
function(htEdgeMap){
for (var i = this.edges.size(); --i >= 0; ) htEdgeMap.put(JS.SmilesRing.getKey(this.edges.get(i)), this.$set);

}, "java.util.Hashtable");
c$.getSetByEdge = Clazz_defineMethod(c$, "getSetByEdge", 
function(edge, htEdgeMap){
return htEdgeMap.get(JS.SmilesRing.getKey(edge));
}, "JU.Edge,java.util.Hashtable");
c$.getKey = Clazz_defineMethod(c$, "getKey", 
function(e){
var i = e.getAtomIndex1();
var j = e.getAtomIndex2();
return (i < j ? i + "_" + j : j + "_" + i);
}, "JU.Edge");
});
;//5.0.1-v7 Thu Feb 05 13:38:23 CST 2026
Clazz_declarePackage("JS");
Clazz_load(["JU.Lst", "$.BS"], "JS.SmilesRingSet", null, function(){
var c$ = Clazz_decorateAsClass(function(){
this.bs = null;
Clazz_instantialize(this, arguments);}, JS, "SmilesRingSet", JU.Lst);
Clazz_prepareFields (c$, function(){
this.bs =  new JU.BS();
});
Clazz_makeConstructor(c$, 
function(){
Clazz_superConstructor (this, JS.SmilesRingSet, []);
});
Clazz_defineMethod(c$, "addSet", 
function(set, htEdgeMap){
for (var i = set.size(); --i >= 0; ) {
var r = set.get(i);
this.addRing(r);
r.addEdges(htEdgeMap);
}
}, "JS.SmilesRingSet,java.util.Hashtable");
Clazz_defineMethod(c$, "addRing", 
function(ring){
this.addLast(ring);
ring.$set = this;
this.bs.or(ring);
}, "JS.SmilesRing");
Clazz_defineMethod(c$, "getElectronCount", 
function(eCounts){
var eCount = 0;
for (var j = this.bs.nextSetBit(0); j >= 0; j = this.bs.nextSetBit(j + 1)) eCount += eCounts[j];

return eCount;
}, "~A");
});
;//5.0.1-v7 Thu Feb 05 13:38:23 CST 2026
Clazz_declarePackage("JS");
Clazz_load(["JU.P3", "JU.Node"], "JS.SmilesAtom", ["JU.AU", "JU.Elements", "$.Logger", "JV.JC"], function(){
var c$ = Clazz_decorateAsClass(function(){
this.patternIndex = -1;
this.pattern = null;
this.primitiveType = 0;
this.isAND = false;
this.subAtoms = null;
this.nSubAtoms = 0;
this.index = 0;
this.referance = null;
this.residueName = null;
this.residueChar = null;
this.insCode = '\0';
this.isBioAtom = false;
this.isBioResidue = false;
this.isBioAtomWild = false;
this.bioType = '\0';
this.$isLeadAtom = false;
this.notBondedIndex = -1;
this.notCrossLinked = false;
this.aromaticAmbiguous = true;
this.covalentHydrogenCount = -1;
this.not = false;
this.selected = false;
this.hasSymbol = false;
this.elementDefined = false;
this.atomType = null;
this.bioAtomName = null;
this.isFirst = true;
this.jmolIndex = -1;
this.elementNumber = -2;
this.atomNumber = -2147483648;
this.residueNumber = -2147483648;
this.explicitHydrogenCount = -2147483648;
this.implicitHydrogenCount = -2147483648;
this.parent = null;
this.bonds = null;
this.bondCount = 0;
this.iNested = 0;
this.isAromatic = false;
this.atomicMass = -2147483648;
this.charge = -2147483648;
this.matchingIndex = -1;
this.stereo = null;
this.component = -2147483648;
this.matchingComponent = 0;
this.atomSite = 0;
this.degree = -1;
this.nonhydrogenDegree = -1;
this.valence = 0;
this.connectivity = -1;
this.ringMembership = -2147483648;
this.ringSize = -2147483648;
this.ringConnectivity = -1;
this.matchingNode = null;
this.hasSubpattern = false;
this.mapIndex = -1;
this.atomClass = NaN;
this.symbol = null;
this.isTopoAtom = false;
this.missingHydrogenCount = 0;
this.cipChirality = 0;
this.hasDoubleBond = false;
Clazz_instantialize(this, arguments);}, JS, "SmilesAtom", JU.P3, JU.Node);
Clazz_prepareFields (c$, function(){
this.bonds =  new Array(4);
});
Clazz_makeConstructor(c$, 
function(){
Clazz_superConstructor (this, JS.SmilesAtom, []);
});
c$.allowSmilesUnbracketed = Clazz_defineMethod(c$, "allowSmilesUnbracketed", 
function(xx){
return ("B, C, N, O, P, S, F, Cl, Br, I, *,".indexOf(xx + ",") >= 0);
}, "~S");
Clazz_overrideMethod(c$, "getAtomType", 
function(){
return (this.atomType == null ? this.bioAtomName : this.atomType);
});
Clazz_defineMethod(c$, "getChiralClass", 
function(){
return (this.stereo == null ? -2147483648 : this.stereo.getChiralClass(this));
});
Clazz_defineMethod(c$, "isDefined", 
function(){
return (this.hasSubpattern || this.iNested != 0 || this.isBioAtom || this.component != -2147483648 || this.elementNumber != -2 || this.nSubAtoms > 0);
});
Clazz_defineMethod(c$, "setBioAtom", 
function(bioType){
this.isBioAtom = (bioType != '\0');
this.bioType = bioType;
if (this.parent != null) {
this.parent.bioType = bioType;
this.parent.isBioAtom = this.isBioAtom;
this.parent.isBioAtomWild = this.isBioAtomWild;
}}, "~S");
Clazz_defineMethod(c$, "setAtomName", 
function(name){
if (name == null) return;
if (name.length > 0) this.bioAtomName = name;
if (name.equals("\0")) this.$isLeadAtom = true;
if (this.parent != null) {
this.parent.bioAtomName = name;
}}, "~S");
Clazz_defineMethod(c$, "setBonds", 
function(bonds){
this.bonds = bonds;
}, "~A");
Clazz_defineMethod(c$, "addSubAtom", 
function(sAtom, isAND){
this.isAND = isAND;
if (this.subAtoms == null) this.subAtoms =  new Array(2);
if (this.nSubAtoms >= this.subAtoms.length) this.subAtoms = JU.AU.doubleLength(this.subAtoms);
sAtom.setIndex(this.index);
sAtom.parent = this;
this.subAtoms[this.nSubAtoms++] = sAtom;
this.setSymbol("*");
this.hasSymbol = false;
return sAtom;
}, "JS.SmilesAtom,~B");
Clazz_defineMethod(c$, "setIndex", 
function(index){
this.index = index;
return this;
}, "~N");
Clazz_defineMethod(c$, "setTopoAtom", 
function(iComponent, ptAtom, symbol, charge, patternIndex){
this.component = iComponent;
this.index = ptAtom;
this.patternIndex = patternIndex;
this.setSymbol(symbol);
this.charge = charge;
this.isTopoAtom = true;
return this;
}, "~N,~N,~S,~N,~N");
Clazz_defineMethod(c$, "setHydrogenCount", 
function(){
this.missingHydrogenCount = this.explicitHydrogenCount;
if (this.explicitHydrogenCount != -2147483648) return true;
var charge = this.getFormalCharge();
var count = JS.SmilesAtom.getDefaultHCount(this.elementNumber, this.isAromatic, charge == -2147483648 ? 0 : charge);
if (count < 0) {
this.missingHydrogenCount = 0;
return (count == -1);
}if (this.elementNumber == 7 && this.isAromatic && this.bondCount == 2) {
if (this.bonds[0].getBondType() == 1 && this.bonds[1].getBondType() == 1) count++;
}for (var i = 0; i < this.bondCount; i++) {
var bond = this.bonds[i];
switch (bond.getBondType()) {
case 81:
if (this.elementNumber == 7) {
JU.Logger.info("Ambiguous bonding to aromatic N found -- MF may be in error");
}count -= 1;
break;
case 1025:
case 1041:
case 65537:
case 65538:
count -= 1;
break;
case 2:
count -= (this.isAromatic && this.elementNumber == 6 ? 1 : 2);
break;
case 1:
case 3:
case 4:
count -= bond.getBondType();
break;
}
}
if (count >= 0) this.missingHydrogenCount = this.explicitHydrogenCount = count;
return true;
});
c$.getDefaultHCount = Clazz_defineMethod(c$, "getDefaultHCount", 
function(elementNumber, isAromatic, charge){
switch (elementNumber) {
case 0:
case -1:
case -2:
return -1;
case 1:
return 1;
case 6:
return (isAromatic ? 3 : 4) + (charge == 0 ? 0 : 1);
case 8:
case 16:
return 2 + charge;
case 7:
return (isAromatic ? 2 : 3) + charge;
case 5:
case 15:
return 3;
case 9:
case 17:
case 35:
case 53:
return 1 + charge;
default:
return 0;
}
}, "~N,~B,~N");
Clazz_overrideMethod(c$, "getIndex", 
function(){
return this.index;
});
Clazz_defineMethod(c$, "setSymbol", 
function(symbol){
this.symbol = symbol;
this.isAromatic = symbol.equals(symbol.toLowerCase());
this.hasSymbol = true;
this.elementDefined = true;
if (symbol.equals("*")) {
this.isAromatic = false;
this.elementNumber = -2;
return true;
}if (symbol.equals("Xx")) {
this.elementNumber = 0;
return true;
}this.aromaticAmbiguous = false;
if (symbol.equals("a") || symbol.equals("A")) {
if (this.elementNumber < 0) this.elementNumber = -1;
return true;
}if (this.isAromatic) symbol = symbol.substring(0, 1).toUpperCase() + (symbol.length == 1 ? "" : symbol.substring(1));
this.elementNumber = JU.Elements.elementNumberFromSymbol(symbol, true);
return (this.elementNumber != 0);
}, "~S");
Clazz_overrideMethod(c$, "getElementNumber", 
function(){
return this.elementNumber;
});
Clazz_defineMethod(c$, "getAtomicMass", 
function(){
return this.atomicMass;
});
Clazz_overrideMethod(c$, "getAtomNumber", 
function(){
return this.atomNumber;
});
Clazz_defineMethod(c$, "setAtomicMass", 
function(mass){
this.atomicMass = mass;
}, "~N");
Clazz_defineMethod(c$, "getCharge", 
function(){
return this.charge;
});
Clazz_defineMethod(c$, "setCharge", 
function(charge){
this.charge = charge;
}, "~N");
Clazz_defineMethod(c$, "getMatchingAtomIndex", 
function(){
return this.matchingIndex;
});
Clazz_defineMethod(c$, "getMatchingAtom", 
function(){
return this.matchingNode == null ? this : this.matchingNode;
});
Clazz_defineMethod(c$, "setMatchingAtom", 
function(jmolAtom, index){
this.matchingNode = jmolAtom;
this.matchingIndex = index;
}, "JU.Node,~N");
Clazz_defineMethod(c$, "setExplicitHydrogenCount", 
function(count){
this.explicitHydrogenCount = count;
}, "~N");
Clazz_defineMethod(c$, "setImplicitHydrogenCount", 
function(count){
this.implicitHydrogenCount = count;
}, "~N");
Clazz_defineMethod(c$, "setDegree", 
function(degree){
this.degree = degree;
}, "~N");
Clazz_defineMethod(c$, "setNonhydrogenDegree", 
function(degree){
this.nonhydrogenDegree = degree;
}, "~N");
Clazz_defineMethod(c$, "setValence", 
function(valence){
this.valence = valence;
}, "~N");
Clazz_defineMethod(c$, "setConnectivity", 
function(connectivity){
this.connectivity = connectivity;
}, "~N");
Clazz_defineMethod(c$, "setRingMembership", 
function(rm){
this.ringMembership = rm;
}, "~N");
Clazz_defineMethod(c$, "setRingSize", 
function(rs){
this.ringSize = rs;
if (this.ringSize == 500 || this.ringSize == 600) this.isAromatic = true;
}, "~N");
Clazz_defineMethod(c$, "setRingConnectivity", 
function(rc){
this.ringConnectivity = rc;
}, "~N");
Clazz_overrideMethod(c$, "getModelIndex", 
function(){
return this.component;
});
Clazz_overrideMethod(c$, "getMoleculeNumber", 
function(inModel){
return this.component;
}, "~B");
Clazz_overrideMethod(c$, "getAtomSite", 
function(){
return this.atomSite;
});
Clazz_overrideMethod(c$, "getFormalCharge", 
function(){
return this.charge;
});
Clazz_overrideMethod(c$, "getIsotopeNumber", 
function(){
return this.atomicMass;
});
Clazz_overrideMethod(c$, "getAtomicAndIsotopeNumber", 
function(){
return JU.Elements.getAtomicAndIsotopeNumber(this.elementNumber, this.atomicMass);
});
Clazz_overrideMethod(c$, "getAtomName", 
function(){
return this.bioAtomName == null ? "" : this.bioAtomName;
});
Clazz_overrideMethod(c$, "getGroup3", 
function(allowNull){
return this.residueName == null ? "" : this.residueName;
}, "~B");
Clazz_overrideMethod(c$, "getGroup1", 
function(c0){
return this.residueChar == null ? "" : this.residueChar;
}, "~S");
Clazz_defineMethod(c$, "addBond", 
function(bond){
if (this.bondCount >= this.bonds.length) this.bonds = JU.AU.doubleLength(this.bonds);
this.bonds[this.bondCount] = bond;
if (bond.order == 2) {
this.hasDoubleBond = true;
}this.bondCount++;
}, "JS.SmilesBond");
Clazz_defineMethod(c$, "setBondArray", 
function(){
if (this.bonds.length > this.bondCount) this.bonds = JU.AU.arrayCopyObject(this.bonds, this.bondCount);
if (this.subAtoms != null && this.subAtoms.length > this.nSubAtoms) this.subAtoms = JU.AU.arrayCopyObject(this.subAtoms, this.subAtoms.length);
for (var i = 0; i < this.bonds.length; i++) {
var b = this.bonds[i];
if (this.isBioAtom && b.getBondType() == 17) {
b.order = 112;
} else if (b.order == 2) {
b.atom1.hasDoubleBond = b.atom2.hasDoubleBond = true;
}if (b.atom1.index > b.atom2.index) {
b.switchAtoms();
}}
});
Clazz_overrideMethod(c$, "getEdges", 
function(){
return (this.parent != null ? this.parent.getEdges() : this.bonds);
});
Clazz_defineMethod(c$, "getBond", 
function(number){
return (this.parent != null ? this.parent.getBond(number) : number >= 0 && number < this.bondCount ? this.bonds[number] : null);
}, "~N");
Clazz_overrideMethod(c$, "getCovalentBondCount", 
function(){
return this.getBondCount();
});
Clazz_overrideMethod(c$, "getBondCount", 
function(){
return (this.parent != null ? this.parent.getBondCount() : this.bondCount);
});
Clazz_overrideMethod(c$, "getCovalentBondCountPlusMissingH", 
function(){
return this.getBondCount() + (this.isTopoAtom ? 0 : this.missingHydrogenCount);
});
Clazz_overrideMethod(c$, "getTotalHydrogenCount", 
function(){
return this.getCovalentHydrogenCount() + (this.isTopoAtom ? 0 : this.missingHydrogenCount);
});
Clazz_overrideMethod(c$, "getImplicitHydrogenCount", 
function(){
return this.implicitHydrogenCount;
});
Clazz_overrideMethod(c$, "getExplicitHydrogenCount", 
function(){
return this.explicitHydrogenCount;
});
Clazz_defineMethod(c$, "getMatchingBondedAtom", 
function(i){
if (this.parent != null) return this.parent.getMatchingBondedAtom(i);
if (i >= this.bondCount) return -1;
var b = this.bonds[i];
return (b.atom1 === this ? b.atom2 : b.atom1).matchingIndex;
}, "~N");
Clazz_overrideMethod(c$, "getBondedAtomIndex", 
function(j){
return (this.parent != null ? this.parent.getBondedAtomIndex(j) : this.bonds[j].getOtherAtom(this).index);
}, "~N");
Clazz_overrideMethod(c$, "getCovalentHydrogenCount", 
function(){
if (this.covalentHydrogenCount >= 0) return this.covalentHydrogenCount;
if (this.parent != null) return (this.covalentHydrogenCount = this.parent.getCovalentHydrogenCount());
this.covalentHydrogenCount = 0;
for (var k = 0; k < this.bonds.length; k++) if (this.bonds[k].getOtherAtom(this).elementNumber == 1) this.covalentHydrogenCount++;

return this.covalentHydrogenCount;
});
Clazz_overrideMethod(c$, "getValence", 
function(){
if (this.parent != null) return this.parent.getValence();
var n = this.valence;
if (n <= 0 && this.bonds != null) for (var i = this.bondCount; --i >= 0; ) n += this.bonds[i].getValence();

this.valence = n;
return n;
});
Clazz_overrideMethod(c$, "getTotalValence", 
function(){
return this.getValence() + (this.isTopoAtom ? 0 : this.missingHydrogenCount);
});
Clazz_defineMethod(c$, "getBondTo", 
function(atom){
if (this.parent != null) return this.parent.getBondTo(atom);
var bond;
for (var k = 0; k < this.bonds.length; k++) {
if ((bond = this.bonds[k]) == null) continue;
if (atom == null ? bond.atom2 === this : bond.getOtherAtom(this) === atom) return bond;
}
return null;
}, "JS.SmilesAtom");
Clazz_defineMethod(c$, "getBondNotTo", 
function(atom, allowH){
var bond;
for (var k = 0; k < this.bonds.length; k++) {
if ((bond = this.bonds[k]) == null) continue;
var atom2 = bond.getOtherAtom(this);
if (atom !== atom2 && (allowH || atom2.elementNumber != 1)) return bond;
}
return null;
}, "JS.SmilesAtom,~B");
Clazz_overrideMethod(c$, "isLeadAtom", 
function(){
return this.$isLeadAtom;
});
Clazz_overrideMethod(c$, "getOffsetResidueAtom", 
function(name, offset){
if (this.isBioAtom) {
if (offset == 0) return this.index;
for (var k = 0; k < this.bonds.length; k++) if (this.bonds[k].getAtomIndex1() == this.index && this.bonds[k].getBondType() == 96) return this.bonds[k].getOtherAtom(this).index;

}return -1;
}, "~S,~N");
Clazz_overrideMethod(c$, "getGroupBits", 
function(bs){
bs.set(this.index);
return;
}, "JU.BS");
Clazz_overrideMethod(c$, "isCrossLinked", 
function(node){
var bond = this.getBondTo(node);
return bond.isHydrogen();
}, "JU.Node");
Clazz_overrideMethod(c$, "getCrossLinkVector", 
function(vLinks, crosslinkCovalent, crosslinkHBond){
var haveCrossLinks = false;
for (var k = 0; k < this.bonds.length; k++) if (this.bonds[k].order == 112) {
if (vLinks == null) return true;
vLinks.addLast(Integer.$valueOf(this.index));
vLinks.addLast(Integer.$valueOf(this.bonds[k].getOtherAtom(this).index));
vLinks.addLast(Integer.$valueOf(this.bonds[k].getOtherAtom(this).index));
haveCrossLinks = true;
}
return haveCrossLinks;
}, "JU.Lst,~B,~B");
Clazz_overrideMethod(c$, "getBioStructureTypeName", 
function(){
return null;
});
Clazz_overrideMethod(c$, "getInsertionCode", 
function(){
return this.insCode;
});
Clazz_overrideMethod(c$, "getResno", 
function(){
return this.residueNumber;
});
Clazz_overrideMethod(c$, "getChainID", 
function(){
return 0;
});
Clazz_overrideMethod(c$, "getChainIDStr", 
function(){
return "";
});
c$.getAtomLabel = Clazz_defineMethod(c$, "getAtomLabel", 
function(atomicNumber, isotopeNumber, valence, charge, osclass, nH, isAromatic, stereo, is2D){
var sym = JU.Elements.elementSymbolFromNumber(atomicNumber);
if (atomicNumber == 1 || isAromatic && !(sym = sym.toLowerCase()).equals("c") && !sym.equals("o") && !sym.equals("s")) {
valence = 2147483647;
}var simple = (valence != 2147483647 && isotopeNumber <= 0 && charge == 0 && Float.isNaN(osclass) && (stereo == null || stereo.length == 0));
var norm = JS.SmilesAtom.getDefaultHCount(atomicNumber, false, charge == -2147483648 ? 0 : charge);
if (is2D && nH == 0) {
if (simple && atomicNumber == 6) return sym;
nH = norm - valence;
}return (simple && norm == valence ? sym : "[" + (isotopeNumber <= 0 ? "" : "" + isotopeNumber) + sym + (stereo == null ? "" : stereo) + (nH > 1 ? "H" + nH : nH == 1 ? "H" : "") + (charge == -2147483648 || charge == 0 ? "" : charge < 0 ? "" + charge : "+" + charge) + (Float.isNaN(osclass) ? "" : ":" + Clazz_floatToInt(osclass)) + "]");
}, "~N,~N,~N,~N,~N,~N,~B,~S,~B");
Clazz_overrideMethod(c$, "getBioSmilesType", 
function(){
return this.bioType;
});
Clazz_defineMethod(c$, "isNucleic", 
function(){
return this.bioType == 'n' || this.bioType == 'r' || this.bioType == 'd';
});
Clazz_overrideMethod(c$, "isPurine", 
function(){
return this.residueChar != null && this.isNucleic() && "AG".indexOf(this.residueChar) >= 0;
});
Clazz_overrideMethod(c$, "isPyrimidine", 
function(){
return this.residueChar != null && this.isNucleic() && "CTUI".indexOf(this.residueChar) >= 0;
});
Clazz_overrideMethod(c$, "isDeleted", 
function(){
return false;
});
Clazz_overrideMethod(c$, "findAtomsLike", 
function(substring){
return null;
}, "~S");
Clazz_overrideMethod(c$, "getFloatProperty", 
function(property){
if (property === "property_atomclass" && this.atomClass != 0) return this.atomClass;
return NaN;
}, "~S");
Clazz_overrideMethod(c$, "getMass", 
function(){
return this.atomicMass;
});
Clazz_overrideMethod(c$, "getCIPChirality", 
function(doCalculate){
return JV.JC.getCIPChiralityName(this.cipChirality & -225);
}, "~B");
Clazz_overrideMethod(c$, "setCIPChirality", 
function(c){
this.cipChirality = c;
}, "~N");
Clazz_overrideMethod(c$, "getCIPChiralityCode", 
function(){
return this.cipChirality;
});
Clazz_overrideMethod(c$, "getXYZ", 
function(){
return this;
});
Clazz_defineMethod(c$, "getStereo", 
function(){
return this.stereo;
});
Clazz_defineMethod(c$, "getPatternIndex", 
function(){
return this.patternIndex;
});
Clazz_overrideMethod(c$, "modelIsRawPDB", 
function(){
return false;
});
Clazz_defineMethod(c$, "definesStereo", 
function(){
return false;
});
Clazz_defineMethod(c$, "getStereoAtAt", 
function(nodes){
return null;
}, "~A");
Clazz_defineMethod(c$, "isStereoOpposite", 
function(i2, iA, iB){
return null;
}, "~N,~N,~N");
Clazz_overrideMethod(c$, "toString", 
function(){
var s2 = "";
for (var i = 0; i < this.bondCount; i++) s2 += this.bonds[i].getOtherAtom(this).getAtomForToString() + ";bo=" + this.bonds[i].getCovalentOrder() + ", ";

return this.getAtomForToString() + "->" + s2 + "(" + this.x + "," + this.y + "," + this.z + ")";
});
Clazz_defineMethod(c$, "getAtomForToString", 
function(){
var s = (this.residueChar != null || this.residueName != null ? (this.residueChar == null ? this.residueName : this.residueChar) + "." + this.bioAtomName : (this.bioAtomName != null && this.atomNumber != -2147483648 ? null : this.elementNumber == -1 ? "A" : this.elementNumber == -2 ? "*" : JU.Elements.elementSymbolFromNumber(this.elementNumber)));
if (s == null) return this.bioAtomName + " #" + this.atomNumber;
if (this.isAromatic) s = s.toLowerCase();
return "[" + s + '.' + this.index + (this.matchingIndex >= 0 ? "(" + this.matchingNode + ")" : "") + "]";
});
});
;//5.0.1-v7 Tue Feb 10 12:29:49 CST 2026
Clazz_declarePackage("JS");
Clazz_load(["JU.Edge"], "JS.SmilesBond", ["JS.InvalidSmilesException"], function(){
var c$ = Clazz_decorateAsClass(function(){
this.atom1 = null;
this.atom2 = null;
this.isNot = false;
this.matchingBond = null;
this.primitives = null;
this.nPrimitives = 0;
this.bondsOr = null;
this.nBondsOr = 0;
this.isConnection = false;
this.atropType = null;
this.isChain = false;
Clazz_instantialize(this, arguments);}, JS, "SmilesBond", JU.Edge);
Clazz_makeConstructor(c$, 
function(atom1, atom2, bondType, isNot){
Clazz_superConstructor (this, JS.SmilesBond, []);
this.set2(bondType, isNot);
this.set2a(atom1, atom2);
}, "JS.SmilesAtom,JS.SmilesAtom,~N,~B");
c$.getBondOrderString = Clazz_defineMethod(c$, "getBondOrderString", 
function(order){
switch (order) {
case 2:
return "=";
case 3:
return "#";
case 4:
return "$";
default:
return "";
}
}, "~N");
c$.getBondTypeFromCode = Clazz_defineMethod(c$, "getBondTypeFromCode", 
function(code){
switch ((code).charCodeAt(0)) {
case 46:
return 0;
case 45:
return 1;
case 61:
return 2;
case 35:
return 3;
case 36:
return 4;
case 58:
return 17;
case 47:
return 1025;
case 92:
return 1041;
case 94:
return 65537;
case 96:
return 65538;
case 64:
return 65;
case 126:
return 81;
case 43:
return 96;
}
return -1;
}, "~S");
Clazz_defineMethod(c$, "getAtom1", 
function(){
return this.atom1;
});
Clazz_defineMethod(c$, "set", 
function(bond){
this.order = bond.order;
this.isNot = bond.isNot;
this.primitives = bond.primitives;
this.nPrimitives = bond.nPrimitives;
this.bondsOr = bond.bondsOr;
this.nBondsOr = bond.nBondsOr;
this.atropType = bond.atropType;
}, "JS.SmilesBond");
Clazz_defineMethod(c$, "setAtropType", 
function(nn){
this.atropType =  Clazz_newIntArray(-1, [Clazz_doubleToInt(nn / 10) - 1, nn % 10 - 1]);
}, "~N");
Clazz_defineMethod(c$, "setPrimitive", 
function(i){
var p = this.primitives[i];
this.order = p.order;
this.isNot = p.isNot;
this.atropType = p.atropType;
return p;
}, "~N");
Clazz_defineMethod(c$, "addBondOr", 
function(){
if (this.bondsOr == null) this.bondsOr =  new Array(2);
if (this.nBondsOr >= this.bondsOr.length) {
var tmp =  new Array(this.bondsOr.length * 2);
System.arraycopy(this.bondsOr, 0, tmp, 0, this.bondsOr.length);
this.bondsOr = tmp;
}var sBond =  new JS.SmilesBond(null, null, -1, false);
this.bondsOr[this.nBondsOr] = sBond;
this.nBondsOr++;
return sBond;
});
Clazz_defineMethod(c$, "addPrimitive", 
function(){
if (this.primitives == null) this.primitives =  new Array(2);
if (this.nPrimitives >= this.primitives.length) {
var tmp =  new Array(this.primitives.length * 2);
System.arraycopy(this.primitives, 0, tmp, 0, this.primitives.length);
this.primitives = tmp;
}var sBond =  new JS.SmilesBond(null, null, -1, false);
this.primitives[this.nPrimitives] = sBond;
this.nPrimitives++;
return sBond;
});
Clazz_overrideMethod(c$, "toString", 
function(){
return this.atom1 + " -" + (this.isNot ? "!" : "") + this.order + "- " + this.atom2;
});
Clazz_defineMethod(c$, "set2", 
function(bondType, isNot){
this.order = bondType;
this.isNot = isNot;
}, "~N,~B");
Clazz_defineMethod(c$, "set2a", 
function(a1, a2){
if (a1 != null) {
this.atom1 = a1;
a1.addBond(this);
}if (a2 != null) {
this.atom2 = a2;
if (a2.isBioAtomWild && this.atom1.isBioAtomWild) this.order = 96;
a2.isFirst = false;
a2.addBond(this);
}}, "JS.SmilesAtom,JS.SmilesAtom");
Clazz_defineMethod(c$, "setAtom2", 
function(atom, molecule){
this.atom2 = atom;
if (this.atom2 != null) {
atom.addBond(this);
this.isConnection = true;
}}, "JS.SmilesAtom,JS.SmilesSearch");
Clazz_defineMethod(c$, "isFromPreviousTo", 
function(atom){
return (!this.isConnection && this.atom2 === atom);
}, "JS.SmilesAtom");
c$.isBondType = Clazz_defineMethod(c$, "isBondType", 
function(ch, isSearch, isBioSequence){
if (ch == '>') return 1;
if ("-=#$:/\\.~^`+!,&;@".indexOf(ch) < 0) return 0;
if (!isSearch && "-=#$:/\\.~^`".indexOf(ch) < 0) throw  new JS.InvalidSmilesException("SMARTS bond type " + ch + " not allowed in SMILES");
switch ((ch).charCodeAt(0)) {
case 126:
return (isBioSequence ? 0 : 1);
case 94:
case 96:
return -1;
default:
return 1;
}
}, "~S,~B,~B");
Clazz_defineMethod(c$, "getValence", 
function(){
return (this.order & 7);
});
Clazz_defineMethod(c$, "getOtherAtom", 
function(a){
return (this.atom1 === a ? this.atom2 : this.atom1);
}, "JS.SmilesAtom");
Clazz_overrideMethod(c$, "getAtomIndex1", 
function(){
return this.atom1.index;
});
Clazz_overrideMethod(c$, "getAtomIndex2", 
function(){
return this.atom2.index;
});
Clazz_overrideMethod(c$, "getCovalentOrder", 
function(){
return this.order & 131071;
});
Clazz_overrideMethod(c$, "getOtherNode", 
function(atom){
return (atom === this.atom1 ? this.atom2 : atom === this.atom2 || atom == null ? this.atom1 : null);
}, "JU.SimpleNode");
Clazz_overrideMethod(c$, "isCovalent", 
function(){
return this.order != 112;
});
Clazz_overrideMethod(c$, "isPartial", 
function(){
return false;
});
Clazz_overrideMethod(c$, "isHydrogen", 
function(){
return this.order == 112;
});
Clazz_defineMethod(c$, "switchAtoms", 
function(){
var a = this.atom1;
this.atom1 = this.atom2;
this.atom2 = a;
switch (this.order & 131071) {
case 65537:
this.order = 65538;
break;
case 65538:
this.order = 65537;
break;
case 1025:
this.order = 1041;
break;
case 1041:
this.order = 1025;
break;
}
});
Clazz_defineMethod(c$, "getRealCovalentOrder", 
function(){
switch (this.order & 131071) {
case 65537:
case 65538:
case 1025:
case 1041:
return 1;
}
return this.order & 131071;
});
Clazz_defineMethod(c$, "getMatchingBond", 
function(){
return this.matchingBond == null ? this : this.matchingBond;
});
Clazz_overrideMethod(c$, "getAtom", 
function(i){
return (i == 1 ? this.atom2 : this.atom1);
}, "~N");
});
;//5.0.1-v7 Thu Feb 05 13:38:23 CST 2026
Clazz_declarePackage("JS");
Clazz_load(null, "JS.SmilesMeasure", ["JU.PT"], function(){
var c$ = Clazz_decorateAsClass(function(){
this.search = null;
this.nPoints = 0;
this.type = 0;
this.index = 0;
this.isNot = false;
this.indices = null;
this.minmax = null;
this.points = null;
Clazz_instantialize(this, arguments);}, JS, "SmilesMeasure", null);
Clazz_prepareFields (c$, function(){
this.indices =  Clazz_newIntArray (4, 0);
this.points =  new Array(4);
});
Clazz_makeConstructor(c$, 
function(search, index, type, isNot, minmax){
this.search = search;
this.type = Math.min(4, Math.max(type, 2));
this.index = index;
this.isNot = isNot;
this.minmax = minmax;
for (var i = minmax.length - 2; i >= 0; i -= 2) if (minmax[i] > minmax[i + 1]) {
var min = minmax[i + 1];
minmax[i + 1] = minmax[i];
minmax[i] = min;
}
}, "JS.SmilesSearch,~N,~N,~B,~A");
Clazz_defineMethod(c$, "addPoint", 
function(index){
if (this.nPoints == this.type) return false;
if (this.nPoints == 0) for (var i = 1; i < this.type; i++) this.indices[i] = index + i;

this.indices[this.nPoints++] = index;
return true;
}, "~N");
Clazz_defineMethod(c$, "check", 
function(){
for (var i = 0; i < this.type; i++) {
var iAtom = this.search.patternAtoms[this.indices[i]].getMatchingAtomIndex();
this.points[i] = this.search.target.nodes[iAtom];
}
var d = 0;
switch (this.type) {
case 2:
d = this.points[0].distance(this.points[1]);
break;
case 3:
this.search.v.vA.sub2(this.points[0], this.points[1]);
this.search.v.vB.sub2(this.points[2], this.points[1]);
d = this.search.v.vA.angle(this.search.v.vB) / 0.017453292;
break;
case 4:
d = JS.SmilesMeasure.setTorsionData(this.points[0], this.points[1], this.points[2], this.points[3], this.search.v, true);
break;
}
for (var i = this.minmax.length - 2; i >= 0; i -= 2) if (d >= this.minmax[i] && d <= this.minmax[i + 1]) return !this.isNot;

return this.isNot;
});
c$.setTorsionData = Clazz_defineMethod(c$, "setTorsionData", 
function(pt1a, pt1, pt2, pt2a, v, withDihedral){
v.vTemp1.sub2(pt1a, pt1);
v.vTemp2.sub2(pt2a, pt2);
if (!withDihedral) return 0;
v.vNorm2.sub2(pt1, pt2);
v.vNorm2.normalize();
v.vTemp1.cross(v.vTemp1, v.vNorm2);
v.vTemp1.normalize();
v.vTemp2.cross(v.vTemp2, v.vNorm2);
v.vTemp2.normalize();
v.vNorm3.cross(v.vTemp1, v.vTemp2);
return v.vTemp1.angle(v.vTemp2) / 0.017453292 * (v.vNorm2.dot(v.vNorm3) < 0 ? 1 : -1);
}, "JU.T3,JU.T3,JU.T3,JU.T3,JS.VTemp,~B");
Clazz_overrideMethod(c$, "toString", 
function(){
var s = "(." + "__dat".charAt(this.type) + this.index + ":" + JU.PT.toJSON(null, this.minmax) + ") for";
for (var i = 0; i < this.type; i++) s += " " + (i >= this.nPoints ? "?" : "" + this.indices[i]);

return s;
});
});
;//5.0.1-v7 Thu Feb 05 13:38:23 CST 2026
Clazz_declarePackage("JS");
Clazz_load(["java.util.Hashtable"], "JS.SmilesParser", ["JU.Lst", "$.PT", "$.SB", "JS.InvalidSmilesException", "$.SmilesAtom", "$.SmilesBond", "$.SmilesMeasure", "$.SmilesSearch", "$.SmilesStereo", "JU.Elements", "$.Logger"], function(){
var c$ = Clazz_decorateAsClass(function(){
this.connections = null;
this.htMeasures = null;
this.flags = 0;
this.isSmarts = false;
this.isBioSequence = false;
this.bioType = '\0';
this.braceCount = 0;
this.branchLevel = 0;
this.componentCount = 0;
this.componentParenCount = 0;
this.ignoreStereochemistry = false;
this.bondDirectionPaired = true;
this.isTarget = false;
Clazz_instantialize(this, arguments);}, JS, "SmilesParser", null);
Clazz_prepareFields (c$, function(){
this.connections =  new java.util.Hashtable();
this.htMeasures =  new java.util.Hashtable();
});
Clazz_makeConstructor(c$, 
function(isSmarts, isTarget){
this.isSmarts = isSmarts;
this.isTarget = isTarget;
}, "~B,~B");
c$.newSearch = Clazz_defineMethod(c$, "newSearch", 
function(pattern, isSmarts, isTarget){
return ( new JS.SmilesParser(isSmarts, isTarget)).parse(pattern);
}, "~S,~B,~B");
Clazz_defineMethod(c$, "parse", 
function(pattern){
if (pattern == null) throw  new JS.InvalidSmilesException("expression must not be null");
var search =  new JS.SmilesSearch();
if (this.isSmarts && !this.isTarget) search.pattern0 = pattern;
if (pattern.indexOf("$(select") >= 0) pattern = this.parseNested(search, pattern, "select");
var ret =  Clazz_newIntArray (1, 0);
pattern = JS.SmilesParser.extractFlags(pattern, ret);
this.flags = ret[0];
search.setFlags(this.flags);
if (pattern.indexOf("$") >= 0) pattern = this.parseVariables(pattern);
if (this.isSmarts && pattern.indexOf("[$") >= 0) pattern = this.parseVariableLength(pattern);
if (pattern.indexOf("||") < 0) return this.getSubsearch(search, pattern, this.flags);
var patterns = JU.PT.split(pattern, "||");
var toDo = "";
search.subSearches =  new Array(patterns.length);
for (var i = 0; i < patterns.length; i++) {
var key = "|" + patterns[i] + "|";
if (toDo.indexOf(key) < 0) {
search.subSearches[i] = this.getSubsearch(search, patterns[i], this.flags);
toDo += key;
}}
return search;
}, "~S");
Clazz_defineMethod(c$, "parseVariableLength", 
function(pattern){
var sout =  new JU.SB();
var len = pattern.length - 1;
var nParen = 0;
var haveInternalOr = false;
for (var i = 0; i < len; i++) {
switch ((pattern.charAt(i)).charCodeAt(0)) {
case 40:
nParen++;
break;
case 41:
nParen--;
break;
case 124:
if (nParen > 0) {
haveInternalOr = true;
if (pattern.charAt(i + 1) == '|') {
pattern = pattern.substring(0, i) + pattern.substring(i + 1);
len--;
}}break;
}
}
if (pattern.indexOf("||") >= 0) {
var patterns = JU.PT.split(pattern, "||");
for (var i = 0; i < patterns.length; i++) sout.append("||").append(this.parseVariableLength(patterns[i]));

} else {
var pt = -1;
var ret =  Clazz_newIntArray (1, 0);
var isOK = true;
var bracketed = null;
while ((pt = pattern.indexOf("[$", pt + 1)) >= 0) {
var pt0 = pt;
var min = -2147483648;
var max = -2147483648;
pt = JS.SmilesParser.getDigits(pattern, pt + 2, ret);
min = ret[0];
if (min != -2147483648) {
if (JS.SmilesParser.getChar(pattern, pt) == '-') {
pt = JS.SmilesParser.getDigits(pattern, pt + 1, ret);
max = ret[0];
}}if (JS.SmilesParser.getChar(pattern, pt) != '(') continue;
bracketed = JS.SmilesParser.getSubPattern(pattern, pt0, '[');
if (!bracketed.endsWith(")")) continue;
var pt1 = pt0 + bracketed.length + 2;
var repeat = JS.SmilesParser.getSubPattern(pattern, pt, '(');
var pt2 = pt;
bracketed = JS.SmilesParser.getSubPattern(pattern, pt, '[');
pt += 1 + repeat.length;
if (repeat.indexOf(':') >= 0 && repeat.indexOf('|') < 0) {
var parenCount = 0;
var n = repeat.length;
var ptColon = -1;
for (var i = 0; i < n; i++) {
switch ((repeat.charAt(i)).charCodeAt(0)) {
case 91:
case 40:
parenCount++;
break;
case 41:
case 93:
parenCount--;
break;
case 46:
if (ptColon >= 0 && parenCount == 0) n = i;
break;
case 58:
if (ptColon < 0 && parenCount == 0) ptColon = i;
break;
}
}
if (ptColon > 0) repeat = repeat.substring(0, ptColon) + "(" + repeat.substring(ptColon, n) + ")" + repeat.substring(n);
}if (min == -2147483648) {
var ptOr = repeat.indexOf("|");
if (ptOr >= 0) return this.parseVariableLength(pattern.substring(0, pt0) + "[$1" + pattern.substring(pt2, pt2 + ptOr + 1) + ")]" + pattern.substring(pt1) + "||" + pattern.substring(0, pt0) + "[$1(" + pattern.substring(pt2 + ptOr + 2) + pattern.substring(pt1));
continue;
}if (max == -2147483648) max = min;
if (repeat.indexOf("|") >= 0) repeat = "[$(" + repeat + ")]";
for (var i = min; i <= max; i++) {
var sb =  new JU.SB();
sb.append("||").append(pattern.substring(0, pt0));
for (var j = 0; j < i; j++) sb.append(repeat);

sb.append(pattern.substring(pt1));
sout.appendSB(sb);
}
}
if (!isOK) throw  new JS.InvalidSmilesException("bad variable expression: " + bracketed);
}return (haveInternalOr ? this.parseVariableLength(sout.substring(2)) : sout.length() < 2 ? pattern : sout.substring(2));
}, "~S");
Clazz_defineMethod(c$, "getSubsearch", 
function(parent, pattern, flags){
this.htMeasures =  new java.util.Hashtable();
var search =  new JS.SmilesSearch();
search.setTop(parent);
search.isSmarts = this.isSmarts;
search.pattern = pattern;
search.pattern0 = parent.pattern0;
search.setFlags(flags);
if (pattern.indexOf("$(") >= 0) pattern = this.parseNested(search, pattern, "");
this.parseSmiles(search, pattern, null, false);
if (this.braceCount != 0) throw  new JS.InvalidSmilesException("unmatched '{'");
if (!this.connections.isEmpty()) throw  new JS.InvalidSmilesException("Open connection");
search.set();
if (this.isSmarts) for (var i = search.ac; --i >= 0; ) this.checkNested(search, search.patternAtoms[i], flags);

 else if (!this.isBioSequence) search.elementCounts[1] = search.getMissingHydrogenCount();
if (!this.ignoreStereochemistry && !this.isTarget) this.fixChirality(search);
return search;
}, "JS.SmilesSearch,~S,~N");
Clazz_defineMethod(c$, "checkNested", 
function(search, atom, flags){
if (atom.iNested > 0) {
var o = search.getNested(atom.iNested);
if ((typeof(o)=='string')) {
var s = o;
if (s.startsWith("select")) return;
if (s.charAt(0) != '~' && atom.bioType != '\0') s = "~" + atom.bioType + "~" + s;
var nested = this.getSubsearch(search, s, flags);
if (nested.ac > 0 && nested.patternAtoms[0].selected) atom.selected = true;
search.setNested(atom.iNested, nested);
}}for (var i = 0; i < atom.nSubAtoms; i++) this.checkNested(search, atom.subAtoms[i], flags);

}, "JS.SmilesSearch,JS.SmilesAtom,~N");
Clazz_defineMethod(c$, "fixChirality", 
function(search){
for (var i = search.ac; --i >= 0; ) {
var sAtom = search.patternAtoms[i];
if (sAtom.stereo != null) sAtom.stereo.fixStereo(sAtom);
}
}, "JS.SmilesSearch");
Clazz_defineMethod(c$, "parseSmiles", 
function(search, pattern, currentAtom, isBranchAtom){
var ret =  Clazz_newIntArray (1, 0);
var pt = 0;
var ch;
var bond = null;
var wasMeasure = false;
var wasBranch = false;
loop : while (pattern != null && pattern.length != 0) {
var index = 0;
if (currentAtom == null) {
index = this.checkBioType(pattern, 0);
if (index == pattern.length) pattern += "*";
if (this.isBioSequence) search.needAromatic = search.top.needAromatic = false;
}ch = JS.SmilesParser.getChar(pattern, index);
var haveOpen = this.checkBrace(search, ch, '{');
if (haveOpen) ch = JS.SmilesParser.getChar(pattern, ++index);
if (ch == '(') {
var subString = JS.SmilesParser.getSubPattern(pattern, index, '(');
var isMeasure = (JS.SmilesParser.getChar(pattern, index + 1) == '.');
if (currentAtom == null) {
if (isMeasure || !this.isSmarts) throw  new JS.InvalidSmilesException("No previous atom for measure");
search.haveComponents = true;
do {
this.componentCount++;
this.componentParenCount++;
ch = JS.SmilesParser.getChar(pattern = pattern.substring(1), 0);
} while (ch == '(');
if (!haveOpen && (haveOpen = this.checkBrace(search, ch, '{')) == true) ch = JS.SmilesParser.getChar(pattern = pattern.substring(1), 0);
} else {
wasMeasure = wasBranch = false;
if (subString.startsWith(".")) {
this.parseMeasure(search, subString.substring(1), currentAtom);
wasMeasure = true;
} else if (subString.length == 0 && this.isBioSequence) {
currentAtom.notCrossLinked = true;
} else {
this.branchLevel++;
this.parseSmiles(search, subString, currentAtom, true);
wasBranch = true;
this.branchLevel--;
}index = subString.length + 2;
ch = JS.SmilesParser.getChar(pattern, index);
if (ch == '}' && this.checkBrace(search, ch, '}')) index++;
ch = '\0';
}}if (ch != '\0') {
pt = index;
out : while (ch != '\0') {
switch (JS.SmilesBond.isBondType(ch, this.isSmarts, this.isBioSequence)) {
case 1:
break;
case 0:
break out;
case -1:
if (!((JU.PT.isDigit(JS.SmilesParser.getChar(pattern, ++index)) && index++ > 0 ? JU.PT.isDigit(JS.SmilesParser.getChar(pattern, index++)) : true) && (ch = JS.SmilesParser.getChar(pattern, index)) == '-')) throw  new JS.InvalidSmilesException("malformed atropisomerism bond ^nn-  or ^^nn-");
continue;
}
ch = JS.SmilesParser.getChar(pattern, ++index);
}
ch = JS.SmilesParser.getChar(pattern, index);
if (ch == ')') {
switch ((ch = JS.SmilesParser.getChar(pattern, ++index)).charCodeAt(0)) {
case 0:
case 41:
case 46:
pattern = pattern.substring(index);
this.componentParenCount--;
if (this.componentParenCount >= 0) continue loop;
}
throw  new JS.InvalidSmilesException("invalid continuation after component grouping (SMARTS).(SMARTS)");
}bond = this.parseBond(search, null, pattern.substring(pt, index), null, currentAtom, false, isBranchAtom, index - pt, ret);
if (haveOpen && bond.order != -1) ch = JS.SmilesParser.getChar(pattern, index = pt);
if (this.checkBrace(search, ch, '{')) ch = JS.SmilesParser.getChar(pattern, ++index);
switch ((ch).charCodeAt(0)) {
case 126:
if (bond.order == 0) {
index = this.checkBioType(pattern, index);
if (index == pattern.length) pattern += "*";
}break;
case 40:
do {
this.componentCount++;
this.componentParenCount++;
ch = JS.SmilesParser.getChar(pattern, ++index);
} while (ch == '(');
break;
case 0:
if (bond.order == 0) return;
}
var isConnect = (JU.PT.isDigit(ch) || ch == '%');
var isAtom = (!isConnect && (ch == '_' || ch == '[' || ch == '*' || JU.PT.isLetter(ch)));
if (isConnect) {
if (wasMeasure) throw  new JS.InvalidSmilesException("connection number must immediately follow its connecting atom");
index = JS.SmilesParser.getRingNumber(pattern, index, ch, ret);
var ringNumber = ret[0];
this.parseConnection(search, ringNumber, currentAtom, bond);
bond = null;
} else if (isAtom) {
wasMeasure = wasBranch = false;
switch ((ch).charCodeAt(0)) {
case 91:
case 95:
var subPattern = JS.SmilesParser.getSubPattern(pattern, index, ch);
index += subPattern.length + (ch == '[' ? 2 : 0);
if (this.isBioSequence && ch == '[' && subPattern.indexOf(".") < 0 && subPattern.indexOf("_") < 0) subPattern += ".0";
currentAtom = this.parseAtom(search, null, subPattern, currentAtom, bond, ch == '[', false, isBranchAtom);
currentAtom.hasSubpattern = true;
if (bond.order != -1 && bond.order != 0) this.setBondAtom(bond, null, currentAtom, search);
bond = null;
break;
default:
var ch2 = (!this.isBioSequence && JU.PT.isUpperCase(ch) ? JS.SmilesParser.getChar(pattern, index + 1) : '\0');
if (ch != 'X' || ch2 != 'x') if (!JU.PT.isLowerCase(ch2) || JU.Elements.elementNumberFromSymbol(pattern.substring(index, index + 2), true) == 0) ch2 = '\0';
if (ch2 != '\0' && "NA CA BA PA SC AC Na Ca Ba Pa Sc Ac".indexOf(pattern.substring(index, index + 2)) >= 0) {
ch2 = '\0';
}var size = (JU.PT.isUpperCase(ch) && JU.PT.isLowerCase(ch2) ? 2 : 1);
currentAtom = this.parseAtom(search, null, pattern.substring(index, index + size), currentAtom, bond, false, false, isBranchAtom);
bond = null;
index += size;
}
} else {
throw  new JS.InvalidSmilesException("Unexpected character: " + JS.SmilesParser.getChar(pattern, index));
}ch = JS.SmilesParser.getChar(pattern, index);
if (ch == '}' && this.checkBrace(search, ch, '}')) index++;
}pattern = pattern.substring(index);
isBranchAtom = false;
}
}, "JS.SmilesSearch,~S,JS.SmilesAtom,~B");
Clazz_defineMethod(c$, "parseConnection", 
function(search, ringNum, currentAtom, bond){
var r = Integer.$valueOf(ringNum);
var bond0 = this.connections.get(r);
if (bond0 == null) {
this.connections.put(r, bond);
search.target.ringCount++;
return;
}this.connections.remove(r);
switch (bond.order) {
case -1:
bond.order = (bond0.order != -1 ? bond0.order : this.isSmarts || currentAtom.isAromatic && bond0.atom1.isAromatic ? 81 : 1);
break;
case 1025:
bond.order = 1041;
break;
case 1041:
bond.order = 1025;
break;
}
if (bond0.order != -1 && bond0.order != bond.order || currentAtom === bond0.atom1 || bond0.atom1.getBondTo(currentAtom) != null) throw  new JS.InvalidSmilesException("Bad connection type or atom");
bond0.set(bond);
currentAtom.bondCount--;
bond0.setAtom2(currentAtom, search);
}, "JS.SmilesSearch,~N,JS.SmilesAtom,JS.SmilesBond");
Clazz_defineMethod(c$, "setBondAtom", 
function(bond, a1, a2, search){
bond.set2a(a1, a2);
if (search != null && bond.order == 2 && bond.atom1 != null && bond.atom2 != null && bond.atom1.isAromatic && bond.atom2.isAromatic && ((this.flags & 512) == 0)) search.setFlags(this.flags = (this.flags | 512));
}, "JS.SmilesBond,JS.SmilesAtom,JS.SmilesAtom,JS.SmilesSearch");
c$.getRingNumber = Clazz_defineMethod(c$, "getRingNumber", 
function(pattern, index, ch, ret){
var ringNumber;
switch ((ch).charCodeAt(0)) {
case 37:
if (JS.SmilesParser.getChar(pattern, index + 1) == '(') {
var subPattern = JS.SmilesParser.getSubPattern(pattern, index + 1, '(');
JS.SmilesParser.getDigits(subPattern, 0, ret);
index += subPattern.length + 3;
if (ret[0] < 0) throw  new JS.InvalidSmilesException("Invalid number designation: " + subPattern);
} else {
if (index + 3 <= pattern.length) index = JS.SmilesParser.getDigits(pattern.substring(0, index + 3), index + 1, ret);
if (ret[0] < 10) throw  new JS.InvalidSmilesException("Two digits must follow the % sign");
}ringNumber = ret[0];
break;
default:
ringNumber = ch.charCodeAt(0) - 48;
index++;
}
ret[0] = ringNumber;
return index;
}, "~S,~N,~S,~A");
Clazz_defineMethod(c$, "checkBioType", 
function(pattern, index){
this.isBioSequence = (pattern.charAt(index) == '~');
if (this.isBioSequence) {
index++;
this.bioType = '*';
var ch = JS.SmilesParser.getChar(pattern, 2);
if (ch == '~' && ((ch = pattern.charAt(1)) == '*' || JU.PT.isLowerCase(ch))) {
this.bioType = ch;
index = 3;
}}return index;
}, "~S,~N");
Clazz_defineMethod(c$, "parseMeasure", 
function(search, strMeasure, currentAtom){
var pt = strMeasure.indexOf(":");
var id = (pt < 0 ? strMeasure : strMeasure.substring(0, pt));
while (pt != 0) {
var len = id.length;
if (len == 1) id += "0";
var m = this.htMeasures.get(id);
if ((m == null) == (pt < 0) || len == 0) break;
try {
if (pt > 0) {
var type = ("__dat".indexOf(id.charAt(0)));
if (type < 2) break;
var ret =  Clazz_newIntArray (1, 0);
JS.SmilesParser.getDigits(id, 1, ret);
var index = ret[0];
strMeasure = strMeasure.substring(pt + 1);
var isNot = strMeasure.startsWith("!");
if (isNot) strMeasure = strMeasure.substring(1);
var isNegative = (strMeasure.startsWith("-"));
if (isNegative) strMeasure = strMeasure.substring(1);
strMeasure = JU.PT.rep(strMeasure, "-", ",");
strMeasure = JU.PT.rep(strMeasure, ",,", ",-");
if (isNegative) strMeasure = "-" + strMeasure;
var tokens = JU.PT.split(strMeasure, ",");
if (tokens.length % 2 == 1 || isNot && tokens.length != 2) break;
var vals =  Clazz_newFloatArray (tokens.length, 0);
var i = tokens.length;
for (; --i >= 0; ) if (Float.isNaN(vals[i] = Float.parseFloat(tokens[i]))) break;

if (i >= 0) break;
m =  new JS.SmilesMeasure(search, index, type, isNot, vals);
search.measures.addLast(m);
if (index > 0) this.htMeasures.put(id, m);
 else if (index == 0 && JU.Logger.debugging) JU.Logger.debug("measure created: " + m);
} else {
if (!m.addPoint(currentAtom.index)) break;
if (m.nPoints == m.type) {
this.htMeasures.remove(id);
if (JU.Logger.debugging) JU.Logger.debug("measure created: " + m);
}return;
}if (!m.addPoint(currentAtom.index)) break;
} catch (e) {
if (Clazz_exceptionOf(e,"NumberFormatException")){
break;
} else {
throw e;
}
}
return;
}
throw  new JS.InvalidSmilesException("invalid measure: " + strMeasure);
}, "JS.SmilesSearch,~S,JS.SmilesAtom");
Clazz_defineMethod(c$, "checkBrace", 
function(search, ch, type){
switch ((ch).charCodeAt(0)) {
case 123:
if (ch != type) break;
this.braceCount++;
search.top.haveSelected = true;
return true;
case 125:
if (ch != type) break;
if (this.braceCount > 0) {
this.braceCount--;
return true;
}break;
default:
return false;
}
throw  new JS.InvalidSmilesException("Unmatched '}'");
}, "JS.SmilesSearch,~S,~S");
Clazz_defineMethod(c$, "parseNested", 
function(search, pattern, prefix){
var index;
prefix = "$(" + prefix;
while ((index = pattern.lastIndexOf(prefix)) >= 0) {
var s = JS.SmilesParser.getSubPattern(pattern, index + 1, '(');
var pt = index + s.length + 3;
var ext = pattern.substring(pt);
pattern = pattern.substring(0, index);
var op = "";
if (pattern.endsWith("]")) throw  new JS.InvalidSmilesException("$(...) must be enclosed in brackets: " + pattern + "$(" + s + ")");
if (index > 1 && prefix.length == 2 && ((pt = pattern.length) > 1 && ",;&![".indexOf(pattern.substring(pt - 1)) < 0)) op = "&";
if (ext.length > 1 && ",;&!)]".indexOf(ext.charAt(0)) < 0) ext = "&" + ext;
pattern = pattern + op + "_" + search.top.addNested(s) + "_" + ext;
}
return pattern;
}, "JS.SmilesSearch,~S,~S");
Clazz_defineMethod(c$, "parseVariables", 
function(pattern){
var keys =  new JU.Lst();
var values =  new JU.Lst();
var index;
var ipt = 0;
var iptLast = -1;
if (JU.Logger.debugging) JU.Logger.info(pattern);
while ((index = pattern.indexOf("$", ipt)) >= 0) {
if (JS.SmilesParser.getChar(pattern, index + 1) == '(') break;
ipt = JS.SmilesParser.skipTo(pattern, index, '=');
if (ipt <= index + 1 || JS.SmilesParser.getChar(pattern, ipt + 1) != '\"') break;
var key = pattern.substring(index, ipt);
if (key.lastIndexOf('$') > 0 || key.indexOf(']') > 0) throw  new JS.InvalidSmilesException("Invalid variable name: " + key);
var s = JS.SmilesParser.getSubPattern(pattern, ipt + 1, '\"');
keys.addLast("[" + key + "]");
values.addLast(s);
ipt += s.length + 2;
ipt = JS.SmilesParser.skipTo(pattern, ipt, ';');
iptLast = ++ipt;
}
if (iptLast < 0) return pattern;
pattern = pattern.substring(iptLast);
for (var i = keys.size(); --i >= 0; ) {
var k = keys.get(i);
var v = values.get(i);
if (!v.equals(k)) pattern = JU.PT.rep(pattern, k, v);
}
if (JU.Logger.debugging) JU.Logger.info(pattern);
return pattern;
}, "~S");
Clazz_defineMethod(c$, "parseAtom", 
function(search, atomSet, pattern, atom, bond, isBracketed, isAND, isBranchAtom){
if (pattern == null || pattern.length == 0) throw  new JS.InvalidSmilesException("Empty atom definition");
var newAtom =  new JS.SmilesAtom();
if (this.componentParenCount > 0) newAtom.component = this.componentCount;
if (atomSet == null) search.appendAtom(newAtom);
var isNewAtom = true;
if (!this.checkLogic(search, pattern, newAtom, null, atom, isAND, isBranchAtom, null)) {
var ret =  Clazz_newIntArray (1, 0);
if (this.isBioSequence && pattern.length == 1) pattern += ".0";
var ch = pattern.charAt(0);
var index = 0;
var isNot = false;
if (this.isSmarts && ch == '!') {
ch = JS.SmilesParser.getChar(pattern, ++index);
if (ch == '\0') throw  new JS.InvalidSmilesException("invalid '!'");
newAtom.not = isNot = true;
}var biopt = (pattern.indexOf("@PH") >= 0 ? -1 : pattern.indexOf('.'));
if (biopt >= 0) {
newAtom.isBioResidue = true;
var resOrName = pattern.substring(index, biopt);
pattern = pattern.substring(biopt + 1).toUpperCase();
var len = resOrName.length;
if ((biopt = resOrName.indexOf("^")) >= 0) {
if (biopt == len - 2) {
ch = resOrName.charAt(len - 1);
if (ch != '*') newAtom.insCode = ch;
}resOrName = resOrName.substring(0, biopt);
}if ((biopt = resOrName.indexOf("#")) >= 0) {
JS.SmilesParser.getDigits(resOrName, biopt + 1, ret);
newAtom.residueNumber = ret[0];
resOrName = resOrName.substring(0, biopt);
}if (resOrName.length == 0) resOrName = "*";
if (resOrName.length > 1) newAtom.residueName = resOrName.toUpperCase();
 else if (!resOrName.equals("*")) newAtom.residueChar = resOrName;
resOrName = pattern;
if ((biopt = resOrName.indexOf("#")) >= 0) {
JS.SmilesParser.getDigits(resOrName, biopt + 1, ret);
newAtom.elementNumber = ret[0];
resOrName = resOrName.substring(0, biopt);
}if (resOrName.length == 0) resOrName = "*";
 else if (resOrName.equals("0")) resOrName = "\0";
if (resOrName.equals("*")) newAtom.isBioAtomWild = true;
 else newAtom.setAtomName(resOrName);
ch = '\0';
}newAtom.setBioAtom(this.bioType);
var hydrogenCount = -2147483648;
while (ch != '\0' && isNewAtom) {
newAtom.setAtomName(this.isBioSequence ? "\0" : "");
if (JU.PT.isDigit(ch)) {
index = JS.SmilesParser.getDigits(pattern, index, ret);
var mass = ret[0];
if (mass == -2147483648) throw  new JS.InvalidSmilesException("Non numeric atomic mass");
if (JS.SmilesParser.getChar(pattern, index) == '?') {
index++;
mass = -mass;
}if (newAtom.elementDefined) throw  new JS.InvalidSmilesException("atom mass must precede atom symbol or be separated from it with \";\"");
newAtom.setAtomicMass(mass);
} else {
switch ((ch).charCodeAt(0)) {
case 34:
var type = JU.PT.getQuotedStringAt(pattern, index);
index += type.length + 2;
newAtom.atomType = type;
break;
case 95:
index = JS.SmilesParser.getDigits(pattern, index + 1, ret) + 1;
if (ret[0] == -2147483648) throw  new JS.InvalidSmilesException("Invalid SEARCH primitive: " + pattern.substring(index));
newAtom.iNested = ret[0];
if (!isBracketed) throw  new JS.InvalidSmilesException("nesting must appear in [...]: $(" + search.getNested(ret[0]) + ")");
if (this.isBioSequence && index != pattern.length) throw  new JS.InvalidSmilesException("invalid characters: " + pattern.substring(index));
break;
case 61:
index = JS.SmilesParser.getDigits(pattern, index + 1, ret);
newAtom.jmolIndex = ret[0];
break;
case 35:
var isAtomNo = (pattern.charAt(index + 1) == '-');
index = JS.SmilesParser.getDigits(pattern, index + (isAtomNo ? 2 : 1), ret);
if (isAtomNo) newAtom.atomNumber = ret[0];
 else newAtom.elementNumber = ret[0];
break;
case 45:
case 43:
index = this.checkCharge(pattern, index, newAtom);
break;
case 64:
if (search.stereo == null) search.stereo = JS.SmilesStereo.newStereo(search);
index = JS.SmilesStereo.checkChirality(search, pattern, index, search.patternAtoms[newAtom.index]);
break;
case 58:
index = JS.SmilesParser.getDigits(pattern, ++index, ret);
if (ret[0] == -2147483648) throw  new JS.InvalidSmilesException("Invalid atom class");
newAtom.atomClass = ret[0];
break;
default:
var nextChar = JS.SmilesParser.getChar(pattern, index + 1);
var len = index + (JU.PT.isLowerCase(nextChar) && (!isBracketed || !JU.PT.isDigit(JS.SmilesParser.getChar(pattern, index + 2))) ? 2 : 1);
var sym2 = pattern.substring(index + 1, len);
var symbol = Character.toUpperCase(ch) + sym2;
var mustBeSymbol = true;
var checkForPrimitive = (isBracketed && JU.PT.isLetter(ch));
if (checkForPrimitive) {
if (!isNot && (isAND ? atomSet : newAtom).hasSymbol) {
mustBeSymbol = false;
} else if (ch == 'H') {
mustBeSymbol = (pattern.length == 1 || !JU.PT.isDigit(nextChar));
} else if (JU.PT.isDigit(nextChar)) {
mustBeSymbol = false;
} else if (!symbol.equals("A") && !symbol.equals("Xx")) {
mustBeSymbol = ((ch == 'h' ? len == 2 : true) && JU.Elements.elementNumberFromSymbol(symbol, true) > 0);
if (!mustBeSymbol && len == 2) {
sym2 = "";
symbol = symbol.substring(0, 1);
mustBeSymbol = (JU.Elements.elementNumberFromSymbol(symbol, true) > 0);
}}}if (mustBeSymbol) {
if (!isBracketed && !this.isSmarts && !this.isBioSequence && !JS.SmilesAtom.allowSmilesUnbracketed(symbol) || !newAtom.setSymbol(symbol = ch + sym2)) throw  new JS.InvalidSmilesException("Invalid atom symbol: " + symbol);
if (isAND) atomSet.hasSymbol = true;
index += symbol.length;
} else {
index = JS.SmilesParser.getDigits(pattern, index + 1, ret);
var val = ret[0];
switch ((ch).charCodeAt(0)) {
default:
throw  new JS.InvalidSmilesException("Invalid SEARCH primitive: " + pattern.substring(index));
case 68:
newAtom.setDegree(val == -2147483648 ? 1 : val);
break;
case 100:
newAtom.setNonhydrogenDegree(val == -2147483648 ? 1 : val);
break;
case 72:
hydrogenCount = (val == -2147483648 ? 1 : val);
break;
case 104:
newAtom.setImplicitHydrogenCount(val == -2147483648 ? -1 : val);
break;
case 82:
if (val == -2147483648) val = -1;
newAtom.setRingMembership(val);
search.top.needRingData = true;
break;
case 114:
if (val == -2147483648) {
val = -1;
newAtom.setRingMembership(val);
} else {
newAtom.setRingSize(val);
switch (val) {
case 500:
val = 5;
break;
case 600:
val = 6;
break;
}
if (val > search.ringDataMax) search.ringDataMax = val;
}search.top.needRingData = true;
break;
case 118:
newAtom.setValence(val == -2147483648 ? 1 : val);
break;
case 88:
newAtom.setConnectivity(val == -2147483648 ? 1 : val);
break;
case 120:
newAtom.setRingConnectivity(val == -2147483648 ? -1 : val);
search.top.needRingData = true;
break;
}
}}
}ch = JS.SmilesParser.getChar(pattern, index);
if (isNot && ch != '\0') throw  new JS.InvalidSmilesException("'!' may only involve one primitive.");
}
if (hydrogenCount == -2147483648 && isBracketed) hydrogenCount = -2147483647;
newAtom.setExplicitHydrogenCount(hydrogenCount);
search.patternAtoms[newAtom.index].setExplicitHydrogenCount(hydrogenCount);
}if (this.braceCount > 0) newAtom.selected = true;
if (isNewAtom && atomSet != null) atomSet.addSubAtom(newAtom, isAND);
if (atom != null && bond.order == 0) {
newAtom.notBondedIndex = atom.index;
}if (atom != null && bond.order != 0) {
if (bond.order == -1) bond.order = (this.isBioSequence && isBranchAtom ? 112 : this.isSmarts || atom.isAromatic && newAtom.isAromatic ? 81 : 1);
if (!isBracketed) this.setBondAtom(bond, null, newAtom, search);
if (this.branchLevel == 0 && (bond.getBondType() == 17 || bond.order == 112)) this.branchLevel++;
}if (this.branchLevel == 0) search.lastChainAtom = newAtom;
return newAtom;
}, "JS.SmilesSearch,JS.SmilesAtom,~S,JS.SmilesAtom,JS.SmilesBond,~B,~B,~B");
Clazz_defineMethod(c$, "checkCharge", 
function(pattern, index, newAtom){
var len = pattern.length;
var ch = pattern.charAt(index);
var count = 1;
++index;
if (index < len) {
var nextChar = pattern.charAt(index);
if (JU.PT.isDigit(nextChar)) {
var ret =  Clazz_newIntArray (1, 0);
index = JS.SmilesParser.getDigits(pattern, index, ret);
count = ret[0];
if (count == -2147483648) throw  new JS.InvalidSmilesException("Non numeric charge");
} else {
while (index < len && pattern.charAt(index) == ch) {
index++;
count++;
}
}}newAtom.setCharge(ch == '+' ? count : -count);
return index;
}, "~S,~N,JS.SmilesAtom");
Clazz_defineMethod(c$, "parseBond", 
function(search, bondSet, pattern, bond, currentAtom, isAND, isBranchAtom, len, ret){
var ch;
if (len > 0) {
switch ((ch = pattern.charAt(0)).charCodeAt(0)) {
case 62:
if (!pattern.equals(">>")) {
len = -1;
break;
}case 46:
if (bond == null && bondSet == null) {
this.isBioSequence = (JS.SmilesParser.getChar(pattern, 1) == '~');
return  new JS.SmilesBond(null, null, 0, false);
}len = -1;
break;
case 43:
if (bondSet != null) len = -1;
break;
}
} else {
ch = '\0';
}var newBond = (bondSet == null ? (bond == null ?  new JS.SmilesBond(currentAtom, null, (this.isBioSequence && currentAtom != null ? (isBranchAtom ? 112 : 96) : -1), false) : bond) : isAND ? bondSet.addPrimitive() : bondSet.addBondOr());
if (len > 0 && !this.checkLogic(search, pattern, null, newBond, currentAtom, isAND, false, ret)) {
var isBondNot = (ch == '!');
if (isBondNot) {
ch = JS.SmilesParser.getChar(pattern, 1);
if (ch == '\0' || ch == '!') throw  new JS.InvalidSmilesException("invalid '!'");
}var bondType = JS.SmilesBond.getBondTypeFromCode(ch);
if (bondType == 65) search.top.needRingMemberships = true;
if (currentAtom == null && bondType != 0) throw  new JS.InvalidSmilesException("Bond without a previous atom");
switch (bondType) {
case 65537:
case 65538:
if ((len = pattern.length) < (isBondNot ? 3 : 2) || pattern.charAt(len - 1) != '-') {
len = 0;
} else {
if (len == (isBondNot ? 3 : 2)) {
newBond.setAtropType(22);
} else {
JS.SmilesParser.getDigits(pattern, (isBondNot ? 2 : 1), ret);
newBond.setAtropType(ret[0]);
}}search.haveBondStereochemistry = true;
break;
case 1025:
case 1041:
this.bondDirectionPaired = !this.bondDirectionPaired;
search.haveBondStereochemistry = true;
break;
case 17:
break;
case 2:
search.top.nDouble++;
case 1:
if (currentAtom.isAromatic) search.top.needRingData = true;
break;
}
newBond.set2(bondType, isBondNot);
if (this.isBioSequence && bondSet != null) bondSet.set2(bondType, isBondNot);
}if (len == -1) throw  new JS.InvalidSmilesException("invalid bond:" + ch);
return newBond;
}, "JS.SmilesSearch,JS.SmilesBond,~S,JS.SmilesBond,JS.SmilesAtom,~B,~B,~N,~A");
Clazz_defineMethod(c$, "checkLogic", 
function(search, pattern, atom, bond, currentAtom, isAND, isBranchAtom, ret){
var pt = pattern.lastIndexOf("!");
if (atom != null) atom.pattern = pattern;
while (pt > 0) {
if (",;&!(".indexOf(pattern.charAt(pt - 1)) < 0) pattern = pattern.substring(0, pt) + "&" + pattern.substring(pt);
pt = pattern.lastIndexOf("!", pt - 1);
}
pt = pattern.indexOf(',');
var len = pattern.length;
var and = "&";
out : while (true) {
var haveOr = (pt > 0);
if (haveOr && !this.isSmarts || pt == 0) break;
pt = pattern.indexOf(';');
if (pt >= 0) {
if (!this.isSmarts || pt == 0) break;
if (haveOr) {
and = ";";
haveOr = false;
} else {
pattern = pattern.$replace(';', '&');
}}var index = 0;
if (haveOr) {
pattern += ",";
while ((pt = pattern.indexOf(',', index)) > 0 && pt <= len) {
var s = pattern.substring(index, pt);
if (s.length == 0) throw  new JS.InvalidSmilesException("missing " + (bond == null ? "atom" : "bond") + " token");
if (bond == null) this.parseAtom(search, atom, s, null, null, true, false, isBranchAtom);
 else this.parseBond(search, bond, s, null, currentAtom, false, false, s.length, ret);
index = pt + 1;
}
} else if ((pt = pattern.indexOf(and)) >= 0 || bond != null && len > 1 && !isAND) {
if (pt == 0 || bond == null && !this.isSmarts) break;
if (bond != null && pt < 0) {
if (len > 1) {
var sNew =  new JU.SB();
for (var i = 0; i < len; ) {
var ch = pattern.charAt(i++);
sNew.appendC(ch);
switch ((ch).charCodeAt(0)) {
case 33:
if (!this.isSmarts) break out;
continue;
case 94:
case 96:
while ((ch = pattern.charAt(i++)) != '-' && ch != '\0') {
sNew.appendC(ch);
}
sNew.appendC('-');
break;
}
if (i < len) {
if (!this.isSmarts) break out;
sNew.append(and);
}}
pattern = sNew.toString();
len = pattern.length;
}}pattern += and;
while ((pt = pattern.indexOf(and, index)) > 0 && pt <= len) {
var s = pattern.substring(index, pt);
if (bond == null) this.parseAtom(search, atom, s, null, null, true, true, isBranchAtom);
 else this.parseBond(search, this.isSmarts ? bond : null, s, this.isSmarts ? null : bond, currentAtom, true, false, s.length, ret);
index = pt + 1;
}
} else {
return false;
}return true;
}
var ch = pattern.charAt(pt);
throw  new JS.InvalidSmilesException((this.isSmarts ? "invalid placement for '" + ch + "'" : "[" + ch + "] notation only valid with SMARTS, not SMILES,") + " in " + pattern);
}, "JS.SmilesSearch,~S,JS.SmilesAtom,JS.SmilesBond,JS.SmilesAtom,~B,~B,~A");
c$.getSubPattern = Clazz_defineMethod(c$, "getSubPattern", 
function(pattern, index, ch){
var ch2;
var margin = 1;
switch ((ch).charCodeAt(0)) {
case 91:
ch2 = ']';
break;
case 34:
case 37:
case 47:
ch2 = ch;
break;
case 40:
ch2 = ')';
break;
default:
ch2 = ch;
margin = 0;
}
var len = pattern.length;
var pCount = 1;
for (var pt = index + 1; pt < len; pt++) {
var ch1 = pattern.charAt(pt);
if (ch1 == ch2) {
pCount--;
if (pCount == 0) return pattern.substring(index + margin, pt + 1 - margin);
} else if (ch1 == ch) {
pCount++;
}}
throw  new JS.InvalidSmilesException("Unmatched " + ch);
}, "~S,~N,~S");
c$.getChar = Clazz_defineMethod(c$, "getChar", 
function(pattern, i){
return (i < pattern.length ? pattern.charAt(i) : '\0');
}, "~S,~N");
c$.getDigits = Clazz_defineMethod(c$, "getDigits", 
function(pattern, index, ret){
var pt = index;
var len = pattern.length;
while (pt < len && JU.PT.isDigit(pattern.charAt(pt))) pt++;

if (pt > index) try {
ret[0] = Integer.parseInt(pattern.substring(index, pt));
return pt;
} catch (e) {
if (Clazz_exceptionOf(e,"NumberFormatException")){
} else {
throw e;
}
}
ret[0] = -2147483648;
return pt;
}, "~S,~N,~A");
c$.skipTo = Clazz_defineMethod(c$, "skipTo", 
function(pattern, index, ch0){
var pt = index;
var ch;
while ((ch = JS.SmilesParser.getChar(pattern, ++pt)) != ch0 && ch != '\0') {
}
return (ch == '\0' ? -1 : pt);
}, "~S,~N,~S");
c$.cleanPattern = Clazz_defineMethod(c$, "cleanPattern", 
function(pattern){
pattern = JU.PT.replaceAllCharacters(pattern, " \t\n\r", "");
pattern = JU.PT.rep(pattern, "^^", "`");
var i = 0;
var i2 = 0;
while ((i = pattern.indexOf("//*")) >= 0 && (i2 = pattern.indexOf("*//")) >= i) pattern = pattern.substring(0, i) + pattern.substring(i2 + 3);

pattern = JU.PT.rep(pattern, "//", "");
return pattern;
}, "~S");
c$.extractFlags = Clazz_defineMethod(c$, "extractFlags", 
function(pattern, ret){
pattern = JS.SmilesParser.cleanPattern(pattern);
var flags = 0;
while (pattern.startsWith("/")) {
var strFlags = JS.SmilesParser.getSubPattern(pattern, 0, '/').toUpperCase();
pattern = pattern.substring(strFlags.length + 2);
flags = JS.SmilesSearch.addFlags(flags, strFlags);
}
ret[0] = flags;
return pattern;
}, "~S,~A");
c$.getFlags = Clazz_defineMethod(c$, "getFlags", 
function(pattern){
var ret =  Clazz_newIntArray (1, 0);
JS.SmilesParser.extractFlags(pattern, ret);
return ret[0];
}, "~S");
});
;//5.0.1-v7 Tue Feb 10 12:29:49 CST 2026
Clazz_declarePackage("JS");
Clazz_load(null, "JS.SmilesExt", ["JU.AU", "$.BS", "$.Lst", "$.M4", "$.Measure", "$.P3", "J.api.Interface", "JU.Logger"], function(){
var c$ = Clazz_decorateAsClass(function(){
this.e = null;
Clazz_instantialize(this, arguments);}, JS, "SmilesExt", null);
/*LV!1824 unnec constructor*/Clazz_defineMethod(c$, "init", 
function(se){
this.e = se;
return this;
}, "~O");
Clazz_defineMethod(c$, "getSmilesCorrelation", 
function(bsA, bsB, smiles, ptsA, ptsB, m4, vReturn, asMap, mapSet, center, bestMap, flags){
var tolerance = (mapSet == null ? 0.1 : 3.4028235E38);
try {
if (ptsA == null) {
ptsA =  new JU.Lst();
ptsB =  new JU.Lst();
}var m =  new JU.M4();
var c =  new JU.P3();
var atoms = this.e.vwr.ms.at;
var ac = this.e.vwr.ms.ac;
var sm = this.e.vwr.getSmilesMatcher();
var maps = sm.getCorrelationMaps(smiles, atoms, ac, bsA, flags | 8);
if (maps == null) this.e.evalError(sm.getLastException(), null);
if (maps.length == 0) return NaN;
var mapFirst = maps[0];
for (var i = 0; i < mapFirst.length; i++) ptsA.addLast(atoms[mapFirst[i]]);

maps = sm.getCorrelationMaps(smiles, atoms, ac, bsB, flags);
if (maps == null) this.e.evalError(sm.getLastException(), null);
if (maps.length == 0) return NaN;
JU.Logger.info(maps.length + " mappings found");
if (bestMap || !asMap) {
var lowestStdDev = 3.4028235E38;
var mapBest = null;
for (var i = 0; i < maps.length; i++) {
ptsB.clear();
for (var j = 0; j < maps[i].length; j++) ptsB.addLast(atoms[maps[i][j]]);

J.api.Interface.getInterface("JU.Eigen", this.e.vwr, "script");
var stddev = (ptsB.size() == 1 ? 0 : JU.Measure.getTransformMatrix4(ptsA, ptsB, m, null));
JU.Logger.info("getSmilesCorrelation stddev=" + stddev);
if (vReturn != null) {
if (stddev < tolerance) {
var bs =  new JU.BS();
for (var j = 0; j < maps[i].length; j++) bs.set(maps[i][j]);

vReturn.addLast(bs);
}}if (stddev < lowestStdDev) {
mapBest = maps[i];
if (m4 != null) m4.setM4(m);
if (center != null) center.setT(c);
lowestStdDev = stddev;
}}
if (mapSet != null) {
mapSet[0] = mapFirst;
mapSet[1] = mapBest;
}ptsB.clear();
for (var i = 0; i < mapBest.length; i++) ptsB.addLast(atoms[mapBest[i]]);

return lowestStdDev;
}for (var i = 0; i < maps.length; i++) for (var j = 0; j < maps[i].length; j++) ptsB.addLast(atoms[maps[i][j]]);


} catch (ex) {
if (Clazz_exceptionOf(ex, Exception)){
this.e.evalError(ex.getMessage(), null);
} else {
throw ex;
}
}
return 0;
}, "JU.BS,JU.BS,~S,JU.Lst,JU.Lst,JU.M4,JU.Lst,~B,~A,JU.P3,~B,~N");
Clazz_defineMethod(c$, "getSmilesMatches", 
function(patternObj, smilesObj, bsSelected, bsMatch3D, flags, asOneBitset, firstMatchOnly){
var info = ((typeof(patternObj)=='string') ? patternObj : "-");
if ((info.length == 0 || info.endsWith("///") || info.equals("H") || info.equals("H2") || info.equals("top") || info.equalsIgnoreCase("NOAROMATIC"))) {
try {
return this.e.vwr.getSmilesOpt(bsSelected, 0, 0, flags | (info.equals("H2") ? 8192 : 0) | (info.equals("H") ? 4096 : 0) | (info.equals("top") ? 16384 : 0) | (info.equalsIgnoreCase("NOAROMATIC") ? 16 : 0), (info.endsWith("///") ? info : null));
} catch (ex) {
if (Clazz_exceptionOf(ex, Exception)){
this.e.evalError(ex.getMessage(), null);
} else {
throw ex;
}
}
}var b;
if (bsMatch3D == null) {
try {
if (smilesObj == null) {
b = this.e.vwr.getSubstructureSetArray(patternObj, bsSelected, flags);
} else if ("chirality".equals(info)) {
return this.e.vwr.calculateChiralityForSmiles(smilesObj.toString());
} else {
var isSmarts = ((flags & 2) == 2);
var ignoreElements = ((flags & 16384) == 16384);
flags = (isSmarts ? 2 : 1) | (firstMatchOnly ? 8 : 0) | (ignoreElements ? 16384 : 0);
if (Clazz_instanceOf(smilesObj,Array)) {
return this.e.vwr.getSmilesMatcher().hasStructure(info, smilesObj, flags);
}var map = this.e.vwr.getSmilesMatcher().find(patternObj, smilesObj, flags);
if (!asOneBitset) return (!firstMatchOnly ? map : map.length == 0 ?  Clazz_newIntArray (0, 0) : map[0]);
var bs =  new JU.BS();
for (var j = 0; j < map.length; j++) {
var a = map[j];
for (var k = a.length; --k >= 0; ) if (a[k] >= 0) bs.set(a[k]);

}
if (!isSmarts) return  Clazz_newIntArray (bs.cardinality(), 0);
var iarray =  Clazz_newIntArray (bs.cardinality(), 0);
var pt = 0;
for (var i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) iarray[pt++] = i;

return iarray;
}} catch (ex) {
if (Clazz_exceptionOf(ex, Exception)){
this.e.evalError(ex.getMessage(), null);
return null;
} else {
throw ex;
}
}
} else {
var vReturn =  new JU.Lst();
var stddev = this.getSmilesCorrelation(bsMatch3D, bsSelected, info, null, null, null, vReturn, false, null, null, false, flags);
if (Float.isNaN(stddev)) return (asOneBitset ?  new JU.BS() :  Clazz_newArray(-1, []));
this.e.showString("RMSD " + stddev + " Angstroms");
b = vReturn.toArray( new Array(vReturn.size()));
}if (asOneBitset) {
var bs =  new JU.BS();
for (var j = 0; j < b.length; j++) bs.or(b[j]);

return bs;
}var list =  new JU.Lst();
for (var j = 0; j < b.length; j++) list.addLast(b[j]);

return list;
}, "~O,~O,JU.BS,JU.BS,~N,~B,~B");
Clazz_defineMethod(c$, "getFlexFitList", 
function(bs1, bs2, smiles1, isSmarts){
var mapSet = JU.AU.newInt2(2);
this.getSmilesCorrelation(bs1, bs2, smiles1, null, null, null, null, false, mapSet, null, false, isSmarts ? 2 : 1);
if (mapSet[0] == null) return null;
var bondMap1 = this.e.vwr.ms.getDihedralMap(mapSet[0]);
var bondMap2 = (bondMap1 == null ? null : this.e.vwr.ms.getDihedralMap(mapSet[1]));
if (bondMap2 == null || bondMap2.length != bondMap1.length) return null;
var angles =  Clazz_newFloatArray (bondMap1.length, 3, 0);
var atoms = this.e.vwr.ms.at;
JS.SmilesExt.getTorsions(atoms, bondMap2, angles, 0);
JS.SmilesExt.getTorsions(atoms, bondMap1, angles, 1);
var data =  Clazz_newFloatArray (bondMap1.length * 6, 0);
for (var i = 0, pt = 0; i < bondMap1.length; i++) {
var map = bondMap1[i];
data[pt++] = map[0];
data[pt++] = map[1];
data[pt++] = map[2];
data[pt++] = map[3];
data[pt++] = angles[i][0];
data[pt++] = angles[i][1];
}
return data;
}, "JU.BS,JU.BS,~S,~B");
c$.getTorsions = Clazz_defineMethod(c$, "getTorsions", 
function(atoms, bondMap, diff, pt){
for (var i = bondMap.length; --i >= 0; ) {
var map = bondMap[i];
var v = JU.Measure.computeTorsion(atoms[map[0]], atoms[map[1]], atoms[map[2]], atoms[map[3]], true);
if (pt == 1) {
if (v - diff[i][0] > 180) v -= 360;
 else if (v - diff[i][0] <= -180) v += 360;
}diff[i][pt] = v;
}
}, "~A,~A,~A,~N");
Clazz_defineMethod(c$, "mapPolyhedra", 
function(i1, i2, isSmiles, m){
var ptsA =  new JU.Lst();
var ptsB =  new JU.Lst();
var data;
data =  Clazz_newArray(-1, [Integer.$valueOf(i1), null]);
this.e.getShapePropertyData(21, "syminfo", data);
var p1 = data[1];
data[0] = Integer.$valueOf(i2);
data[1] = null;
this.e.getShapePropertyData(21, "syminfo", data);
var p2 = data[1];
if (p1 == null || p2 == null) return NaN;
var smiles1 = p1.get("polySmiles");
var smiles2 = p2.get("polySmiles");
var map = this.getSmilesMatches(smiles2, smiles1, null, null, isSmiles ? 1 : 16385, false, true);
if (map.length == 0) return NaN;
ptsA.addLast(p1.get("center"));
var a = p1.get("vertices");
for (var i = 0, n = a.length; i < n; i++) ptsA.addLast(a[map[i + 1] - 1]);

ptsB.addLast(p2.get("center"));
a = p2.get("vertices");
for (var i = 0, n = a.length; i < n; i++) ptsB.addLast(a[i]);

J.api.Interface.getInterface("JU.Eigen", this.e.vwr, "script");
return JU.Measure.getTransformMatrix4(ptsA, ptsB, m, null);
}, "~N,~N,~B,JU.M4");
});
;//5.0.1-v7 Tue Feb 10 12:29:49 CST 2026
})(Clazz
,Clazz.getClassName
,Clazz.newLongArray
,Clazz.doubleToByte
,Clazz.doubleToInt
,Clazz.doubleToLong
,Clazz.declarePackage
,Clazz.instanceOf
,Clazz.load
,Clazz.instantialize
,Clazz.decorateAsClass
,Clazz.floatToInt
,Clazz.floatToLong
,Clazz.makeConstructor
,Clazz.defineEnumConstant
,Clazz.exceptionOf
,Clazz.newIntArray
,Clazz.newFloatArray
,Clazz.declareType
,Clazz.prepareFields
,Clazz.superConstructor
,Clazz.newByteArray
,Clazz.declareInterface
,Clazz.newShortArray
,Clazz.innerTypeInstance
,Clazz.isClassDefined
,Clazz.prepareCallback
,Clazz.newArray
,Clazz.castNullAs
,Clazz.floatToShort
,Clazz.superCall
,Clazz.decorateAsType
,Clazz.newBooleanArray
,Clazz.newCharArray
,Clazz.implementOf
,Clazz.newDoubleArray
,Clazz.overrideConstructor
,Clazz.clone
,Clazz.doubleToShort
,Clazz.getInheritedLevel
,Clazz.getParamsType
,Clazz.isAF
,Clazz.isAB
,Clazz.isAI
,Clazz.isAS
,Clazz.isASS
,Clazz.isAP
,Clazz.isAFloat
,Clazz.isAII
,Clazz.isAFF
,Clazz.isAFFF
,Clazz.tryToSearchAndExecute
,Clazz.getStackTrace
,Clazz.inheritArgs
,Clazz.alert
,Clazz.defineMethod
,Clazz.overrideMethod
,Clazz.declareAnonymous
//,Clazz.checkPrivateMethod
,Clazz.cloneFinals
);
