Advanced Structure Checker Button

    
    /*
    * Advanced Structure Checker Button
    * 
    * Runs the structure checker against the currently selected row
    * Runs in either <check> or <fix> mode
    * Uses XML definition file which can be created with Structure Checker application
    * see https://docs.chemaxon.com/display/structurechecker/Creating+a+Configuration+StrCh
    * for more checkers see:
    * https://docs.chemaxon.com/display/structurechecker/Checker+List
    *
    * Usage:
    * 1. Edit the name of the Structure field
    * 2. Set either <check> or <fix> mode
    * 3. Provide the xmlConfigFilePath parameter
    * 2. Run button script
    *
    * @author David Pech <dpech@chemaxon.com>
    * @author Zsolt Mohacsi <zmohacsi@chemaxon.com>
    */
    import com.im.df.api.*
    import com.im.df.api.support.SelectionDescription
    import com.im.ijc.core.api.util.IJCCoreUtils
    import chemaxon.checkers.*
    import chemaxon.struc.Molecule
    import com.im.df.api.chem.MarvinStructure
    import chemaxon.formats.MolImporter
    import chemaxon.checkers.FixMode;
    import chemaxon.checkers.logger.PropertyCheckerLogger;
    import chemaxon.checkers.runner.AdvancedCheckerRunner;
    import chemaxon.checkers.runner.configuration.reader.ActionStringBasedConfigurationReader;
    import chemaxon.checkers.runner.configuration.reader.ConfigurationReader;
    import chemaxon.checkers.runner.configuration.reader.XMLBasedConfigurationReader;
    init = { widget ->
    }
    destroy = { widget ->
    }
    evaluate = { widget ->
        def ety = dataTree.rootVertex.entity // assumes you have reference to the data tree
        def edp = ety.schema.dataProvider.getEntityDataProvider(ety)
        def molFld = ety.fields.items.find { it.name == 'Structure' } // find the structure field
        def rs = ety.schema.dataProvider.getDefaultResultSet(dataTree, false, DFEnvironmentRO.DEV_NULL) // find the ResultSet
        def rootVS = rs.getVertexState(dataTree.rootVertex) // obtain the VertexState
    
        List ids = rootVS.getSelectedRowsIds() // get the selected IDs
        if (ids.size == 1) {
            Map rows = rootVS.getData(ids, DFEnvironmentRO.DEV_NULL) // get the data
            Map row = rows[ids[0]] // get the first and only row
            MarvinStructure mol = row[molFld.id] // Get the Structure. Its a com.im.df.api.chem.MarvinStructure instance
            Molecule cxnMol = mol.getNative() // obtain the chemaxon.struc.Molecule instance
    
            // parameters for structure checker
            String mode = "fix" // [check|fix] - in fix mode, the structure is rewritten in the database
            String configSource = "xml" // [xml|actionstring]
            String xmlConfigFilePath = "/path/to/checkers.xml" // [<xml config file path>|<action string>]
            // actionString can be used instead of XML configuration
            //String actionString = "" // for example something like "valence->fixvalence"
            // read configuration
            ConfigurationReader checkerConfigurationReader;
            if (configSource.equalsIgnoreCase("xml") && xmlConfigFilePath != null) { // XML configuration
                File configFile = new File(xmlConfigFilePath);
                checkerConfigurationReader = new XMLBasedConfigurationReader(new FileInputStream(configFile));
            } else if (configSource.equalsIgnoreCase("actionstring") && actionString != null) { // action string configuration
                checkerConfigurationReader = new ActionStringBasedConfigurationReader(actionString);
            } else {
                println "Cannot read configuration"
                return;
            }
            // create CheckerRunner
            AdvancedCheckerRunner checkerRunner = new AdvancedCheckerRunner(checkerConfigurationReader);
            // in a non-interactive environment ASK mode has no meaning, so we change it to fix mode
            for (chemaxon.checkers.StructureChecker checker : checkerRunner.getCheckerConfiguration()) {
                if (FixMode.ASK.equals(checker.getDescriptor().getFixMode())) {
                    checker.getDescriptor().setFixMode(FixMode.FIX);
                }
            }
            // set error logger
            PropertyCheckerLogger logger = new PropertyCheckerLogger();
            checkerRunner.setLogger(logger);
            // set molecule
            checkerRunner.setMolecule(cxnMol);
            // run the checker+fixer
            if (mode.equalsIgnoreCase("fix")) {
                checkerRunner.fix()
                // rewrite structure in the database with the fixed one
                // in case that fix mode is set
                def dataToUpdate = [(molFld.id):cxnMol.toFormat("sdf")]
                def lock = edp.lockable.withLock('Updating') { envRW ->
                    def ud = DFUpdateDescription.create(ety, ids[0], dataToUpdate)
                    def submitList = Collections.singletonList(ud)
                    edp.update(submitList, DFUndoConfig.OFF, envRW)
                }
            } else {
                checkerRunner.checkAndWait()
            }
            // see report in molecule properties
            println cxnMol.toFormat("sdf")
    
        } else {
            println "bad selection"
        }
    }
    on_change = { widget, button ->
    
    }
    

    For example Structure Checker configuration see checkers.xml

    Attached, you can also find a version of this script, where the fix|check mode is selected with a checkbox in a popup. StructureCheckerImproved.groovy