libSBML
5.18.0

LibSBML setIdFromNames.java



/**
 * @file    setIdFromNames.java
 * @brief   Utility program, renaming all SIds that also has
 *          names specified. The new id will be derived from
 *          the name, with all invalid characters removed. 
 *
 * @author  Frank T. Bergmann
 *
 * 
 */ 

import java.util.Vector;
import org.sbml.libsbml.IdentifierTransformer;
import org.sbml.libsbml.SBMLDocument;
import org.sbml.libsbml.SBase;
import org.sbml.libsbml.SBaseList;
import org.sbml.libsbml.libsbml;

public class setIdFromNames
    extends IdentifierTransformer
{

    /**
     * @param args
     */
    public static void main(String[] args)
    {
        System.loadLibrary("sbmlj");
        System.out.println("Using libSBML : "
            + libsbml.getLibSBMLDottedVersion());
        if (args.length != 2)
        {
            System.out.format("\nUsage: setIdFromNames filename output\n\n");
            System.exit(1);
        }

        String filename = args[0];
        String output = args[1];

        // read the document
        long start = System.currentTimeMillis();
        SBMLDocument document = libsbml.readSBMLFromFile(filename);
        long stop = System.currentTimeMillis();

        System.out.println();
        System.out.format("            filename: %s\n", filename);
        System.out.format("      read time (ms): %d\n", (stop - start));

        // stop in case of serious errors
        long errors = document.getNumErrors(libsbml.LIBSBML_SEV_ERROR);
        if (errors > 0)
        {
            System.out.format("            error(s): %d\n", errors);
            document.printErrors();
            System.exit((int) errors);
        }

        // get a list of all elements, as we will need to know all identifiers
        // so that we don't create duplicates.
        SBaseList allElements = document.getListOfAllElements();

        // get a list of all ids
        Vector allIds = getAllIds(allElements);

        // create the transformer with the ids
        setIdFromNames trans = new setIdFromNames(allIds);

        // rename the identifiers (using the elements we already gathered
        // before)
        start = System.currentTimeMillis();
        document.getModel().renameIDs(allElements, trans);
        stop = System.currentTimeMillis();
        System.out.format("    rename time (ms): %d\n", (stop - start));

        // write to file
        start = System.currentTimeMillis();
        libsbml.writeSBMLToFile(document, output);
        stop = System.currentTimeMillis();
        System.out.format("     write time (ms): %d\n", (stop - start));
        System.out.println();

        // if we got here all went well ...

    }


    // 
    // Constructor initializing this transformer with a list of
    // ids that are currently used in the model (and thus newly generated
    // ids have to be different)
    // 
    // vector of current ids
    public setIdFromNames(Vector ids)
    {
        existingIds = ids;
    }

    Vector existingIds;


    /**
     * Cleans the name, so it represents a valid SId
     * 
     * Taken from COPASI (released under the artistic license)
     * https://github.com/copasi/COPASI/blob/master/copasi/utilities/utility.cpp
     */
    public String nameToSbmlId(String name)
    {
        // We convert all non allowed characters to '_'
        // letter ::= 'a'..'z','A'..'Z'
        // digit ::= '0'..'9'
        // idChar ::= letter | digit | '_'
        // SId ::= (letter | '_' ) idChar*

        StringBuilder IdStream = new StringBuilder();
        int count = 0;
        int end = name.length();

        if ('0' <= name.charAt(count) && name.charAt(count) <= '9')
        {
            IdStream.append('_');
        }

        for (; count != end; ++count)
        {
            // second, third or forth character of a multi-byte encoding
            if (0x80 == (name.charAt(count) & 0xc0))
            {
                continue;
            }

            if (('0' <= name.charAt(count) && name.charAt(count) <= '9')
                || ('a' <= name.charAt(count) && name.charAt(count) <= 'z')
                || ('A' <= name.charAt(count) && name.charAt(count) <= 'Z'))
            {
                IdStream.append(name.charAt(count));
            }
            else
            {
                IdStream.append('_');
            }
        }

        String Id = IdStream.toString();

        if (Id.charAt(Id.length() - 1) != '_')
        {
            return Id;
        }

        return Id.substring(0, Id.length() - 1);
    }


    /**
     * Generates the id out of the name, and ensures it is unique.
     * It does so by appending numbers to the original name.
     */
    String getValidIdForName(String name)
    {
        String baseString = nameToSbmlId(name);
        String id = baseString;
        int count = 1;
        while (existingIds.contains(id))
        {
            id = String.format("%s_%d", baseString, count);
            ++count;

        }
        return id;
    }


    @Override
    public int transform(SBase element)
    {
        // return in case we don't have a valid element
        if (element == null
            || element.getTypeCode() == libsbml.SBML_LOCAL_PARAMETER)
            return libsbml.LIBSBML_OPERATION_SUCCESS;

        // or if there is nothing to do
        if (!element.isSetName() || element.getId() == element.getName())
            return libsbml.LIBSBML_OPERATION_SUCCESS;

        // find the new id
        String newId = getValidIdForName(element.getName());

        // set it
        element.setId(newId);

        // remember it
        existingIds.add(newId);

        return libsbml.LIBSBML_OPERATION_SUCCESS;
    }


    /**
     * Returns a list of all ids from the given list of elements
     */
    public static Vector getAllIds(SBaseList allElements)
    {
        Vector result = new Vector();
        if (allElements == null || allElements.getSize() == 0) return result;

        for (int i = 0; i < allElements.getSize(); ++i)
        {
            SBase current = allElements.get(i);
            if (current.isSetId()
                && current.getTypeCode() != libsbml.SBML_LOCAL_PARAMETER)
            {
                result.add(current.getId());
            }
        }

        return result;
    }

}

libSBML
5.18.0


LibSBML, an application programming interface (API) library for SBML.