[Uml-user] Java2XMI converter hacked

张钰彦 zhangyy at cmail.cn
Sun Sep 4 00:27:07 UTC 2005


 * Hacked by Hyacinth, Sep 2th, 2005
 *
 * 1. Package distinguish is hacked.
 * 		The old program treats very sub-dir as a Java package except "CVS" dir.
 * 		The new program considers only when a sub-dir contains Java source files as Java package.
 * 		It causes Java string used. So the new program needs more memory for XMI code buffer.
 *
 * 2. The source codes are re-formatted by "astyle -b".
 * 
 * 3. Folding marks are used, the source codes look fine in editors that support "Folding", such as
 *  VIM/Emacs/jEdit/etc.
 *
 *  mrkissinger _at_ gmail.com/msn.com/cmail.cn

-------------- next part --------------
import java.io.*;

/**
 * Java2XMI converter
 *
 *
 * Written by R.Rawson-Tetley, 9th Feb, 2005
 * 
 * Input:  Source Directory containing Java files (as classpath root)
 * Output: XMI description of passed in source files, complete with 
 *         packages, classes, methods, etc
 *
 * Consider this class public domain - do what you want with it.
 * 
 * robin at rawsontetley.org
 *
 *
 * Hacked by Hyacinth, Sep 2th, 2005
 *
 * 1. Package distinguish is hacked.
 * 		The old program treats very sub-dir as a Java package except "CVS" dir.
 * 		The new program considers only when a sub-dir contains Java source files as Java package.
 * 		It causes Java string used. So the new program needs more memory for XMI code buffer.
 *
 * 2. The source codes are re-formatted by "astyle -b".
 * 
 * 3. Folding marks are used, the source codes look fine in editors that support "Folding", such as
 *  VIM/Emacs/jEdit/etc.
 *
 *  mrkissinger _at_ gmail.com/msn.com/cmail.cn
 *
 * 
 */
public class J2XMI
{

    public static void main(String[] args)//{{{
    {

        if (args.length == 0)
        {
            System.out.println("java2xmi 050218 - convert java source to XMI");
            System.out.println("Written by R.Rawson-Tetley");
            System.out.println("");
            System.out.println("This library is distributed in the hope that it will be useful,");
            System.out.println("but WITHOUT ANY WARRANTY; without even the implied warranty of");
            System.out.println("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU");
            System.out.println("General Public Licence for more details.");
            System.out.println("");
            System.out.println("Usage: java2xmi [--noprivate] [--noprotected] <source folder>");
            System.exit(1);
        }
        new J2XMI(args);
    }//}}}

    /** The number of spaces we are currently at to indent the
     *  package/class/interface/operation XMI structures at
     *  This value is incremented/decremented as we traverse
     *  the file tree and find classes
     */
    private int depth = 1;

    /** Whether we are excluding private accessors */
    private boolean noprivate = false;

    /** Whether we are excluding protected accessors */
    private boolean noprotected = false;
    /** The last accessor type return by <code>findNextAccessor</code> */
    public String lastAc = "public";
    private int nextID = 1000;
	
    public J2XMI(String[] args)//{{{
	/**
     *  Construct a new J2XMI with the specified folder and go.
     */
    {

        try
        {
            String src = args[args.length-1];

            for (int i = 0; i < args.length; i++)
            {
                if (args[i].equals("--noprivate"))
                    noprivate = true;
                if (args[i].equals("--noprotected"))
                    noprotected = true;
            }

            File f = new File(src);
            outputHeader();
            System.out.println(traverse(f));
            outputFooter();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            System.exit(1);
        }
    }//}}}

    public String traverse(File f)//{{{
    /**
     *  Enumerates each file for the given directory
     *  and processes it as XMI output: This routine will 
     *  call itself recursively for any directories
     *  it finds whilst processing.
     *
     *  @param f The <code>File</code> to look in
     *  @param firstTime Whether or not it's the first time (and hence
     *         whether we need to output UML package structure)
     */
    {
		/*
		 *	Whether the current dir is a Java package.
		 */
		boolean isPackageDir=false;
		boolean isFirstJavaFile=true;

		String xmiCode="";

        // Move up one depth for indenting XML
        depth++;

        try
        {
            // Output a package element for the directory. We
            // don't want to include the folder to start in though, so if it's
            // the first time, don't bother outputting package details.
			/*
            if (!firstTime)
                System.out.println(getSpaces(depth) + "<UML:Package visibility=\"public\" xmi.id=\"" +
                                   getXmiID() + "\" name=\"" + f.getName() + "\">");
								   */

            File[] d = f.listFiles();
            for (int i = 0; i < d.length; i++)
            {

                // If we have a directory, process it
                if (d[i].isDirectory())
				{
                    // Unless it's a CVS directory
                    if (!d[i].getName().equals("CVS"))
					{
						//System.out.println(d[i].getName());
                        String code=traverse(d[i]);
						if ( (null!=code) )//&& (!f.getName().equals(".")) )
						{
							//System.out.println(d[i].getName());
							/*
							System.out.println(
									getSpaces(depth) + 
									"<UML:Package visibility=\"public\" xmi.id=\"" +
                                   	getXmiID() + "\" name=\"" + d[i].getName() + "\">\n"+
									code+"\n"+
									"</UML:Package>"
									);
							*/
							xmiCode=xmiCode+getSpaces(depth) + 
									"<UML:Package visibility=\"public\" xmi.id=\"" +
                                   	getXmiID() + "\" name=\"" + d[i].getName() + "\">\n"+
									code+"\n"+
									"</UML:Package>\n";
						}
					}
				}

                // If it's a java file, process it
                if (d[i].getName().toLowerCase().endsWith(".java"))
				{
					/*
					if (null==xmiCode)
					{
						xmiCode=new String();
					}
					*/
						
					if (isFirstJavaFile)
					{
						/*
						System.out.println(getSpaces(depth) + "<UML:Package visibility=\"public\" xmi.id=\"" +
                                   getXmiID() + "\" name=\"" + f.getName() + "\">");
								   */



						/*
						xmiCode=xmiCode+getSpaces(depth) + "<UML:Package visibility=\"public\" xmi.id=\"" +
                                   getXmiID() + "\" name=\"" + f.getName() + "\">";
								   */
						isPackageDir=true;
					}
                    xmiCode=xmiCode+processJava(d[i]);
				}
            }
        }
        catch (Exception e)
        {}

        // Close the package element
		/*
        if (!firstTime)
            System.out.println(getSpaces(depth) + "</UML:Package>");
		*/

		//if (isPackageDir)
		{
			//System.out.println(getSpaces(depth) + "</UML:Package>");
			//xmiCode=xmiCode+getSpaces(depth) + "</UML:Package>";
		}

        // Move down a level for indenting XML
        depth--;

		return(xmiCode);

    }//}}}

    public String getSpaces(int num)//{{{
    /**
     * Returns a string of the requested number of spaces.
     *
     * @param num The number of spaces to return
     */
	{
        StringBuffer b = new StringBuffer(num);
        for (int i = 0; i < num; i++)
            b.append(" ");
        return b.toString();
    }//}}}

    public String processJava(File f)//{{{
    /**
     * Process a Java file, outputting details of the class/interface
     * and all methods
     *
     * This is really crude and probably should have been split out
     * into some delegated code that built a tree of objects and
     * then looped through them to generate the XML, but time is
     * a factor and I don't have much to waste working on this
     *
     * @param f The java <code>File</code> to process.
     */
    {

        boolean wroteHeader = false;
        boolean isInterface = true;
		String xmiCode="";

        try
        {

            String s = readFileToString(f);

            // Remove comments since they can confuse us if they
            // have code snippets and things in there
            s = stripComments(f.getName(), s);

            // Look for the first curly brace and then work back
            // to find an interface or class declaration
            int fcb = s.indexOf("{");
            int ipos = s.lastIndexOf(" interface", fcb);
            if (ipos == -1)
            {
                ipos = s.lastIndexOf(" class", fcb);
                isInterface = false;
            }

            // We couldn't find an initial declaration. Abort.
            if (ipos == -1)
            {
                System.err.println(f.getName() + ": Couldn't find initial \"public interface\" or \"public class\" declaration");
                return(xmiCode);
            }

            // Determine the name by looking for a space after
            // the class/interface type
            int namepos = s.indexOf(" ", ipos + 2) + 1;
            // Get the end of the name by looking for the first linebreak/space
            // after the name
            int nameend = getNextWhitespaceChar(s, namepos + 1);
            String name = asXMLAttribute(s.substring(namepos, nameend));

            // Drop a depth level and output the class/interface XMI
            depth++;
            if (isInterface)
			{
				/*
                System.out.println(getSpaces(depth) + "<UML:Interface stereotype=\"42\" " +
                                   "visibility=\"public\" xmi.id=\"" + getXmiID() + "\" isAbstract=\"true\" " +
                                   "name=\"" + asXMLAttribute(name) + "\">");
								   */
				xmiCode=xmiCode+getSpaces(depth) + "<UML:Interface stereotype=\"42\" " +
                                   "visibility=\"public\" xmi.id=\"" + getXmiID() + "\" isAbstract=\"true\" " +
                                   "name=\"" + asXMLAttribute(name) + "\">\n";
			}
            else
			{
				/*
                System.out.println(getSpaces(depth) + "<UML:Class visibility=\"public\" xmi.id=\"" +
                                   getXmiID() + "\" name=\"" + asXMLAttribute(name) + "\">");
								   */
				xmiCode=xmiCode+getSpaces(depth) + "<UML:Class visibility=\"public\" xmi.id=\"" +
                                   getXmiID() + "\" name=\"" + asXMLAttribute(name) + "\">\n";
			}
				

            // Mark the header as written to make sure we write a closer should
            // the worst happen.
            wroteHeader = true;

            // Start looking for methods/fields from the first curly brace
            int pos = fcb;

            // Look for an accessor string that could be the start of a field/method
            // (public/private/protected)
            pos = findNextAccessor(s, pos + 1);

            // Whether we need to abandon during the loop - we need to do this if
            // we find something horrible or unexpected so we don't write crap XMI
            boolean abort = false;

            // Whether we're dealing with a static method/field
            boolean isStatic = false;
            boolean isTransient = false;
            boolean isSynchronized = false;
            boolean isAbstract = false;
            boolean isFinal = false;
            boolean isConstructor = false;

            // Whether this is a field or a method
            boolean isMethod = false;

            // The method/field name and type
            String mname = "";
            String mtype = "";

            // Where split strings go when breaking up the method/field signature
            String[] methodbits = null;

            while (pos != -1)
            {

                abort = false;
                isStatic = false;
                isTransient = false;
                isSynchronized = false;
                isAbstract = false;
                isFinal = false;
                isConstructor = false;
                mname = "";
                mtype = "";
                isMethod = false;

                // Get the next terminator (semi-colon or close bracket);
                // if the next one is a semi-colon, then we're dealing
                // with a field rather than a method.
                int sigterminator = -1;
                for (int i = pos; i < s.length()-1; i++)
                {
                    if (s.substring(i, i+1).equals(";"))
                    {
                        sigterminator = i;
                        isMethod = false;
                        break;
                    }
                    else if (s.substring(i, i+1).equals(")"))
                    {
                        sigterminator = i;
                        isMethod = true;
                        break;
                    }
                }

                if (isMethod)
                {

                    // METHOD PARSER
                    // ================================================================

                    // Read the method signature
                    String msig = "";
                    try
                    {
                        msig = s.substring(pos, sigterminator).trim();
                    }
                    catch (StringIndexOutOfBoundsException e)
                    {
                        // This shouldn't ever happen
                        abort = true;
                        System.err.println("WARN: Couldn't find the end of the method sig - aborting: "
                                           + pos + "-" + sigterminator);
                    }

                    // Verify that the method start we found wasn't
                    // inside a string literal and some smart alec is
                    // running java2xmi over it's own source
                    if (s.substring(pos - 1, pos).equals("\""))
                    {
                        abort = true;
                        System.err.println("WARN: Almost confused by a string literal - aborting:\n  " + msig);
                    }

                    if (!abort)
                    {

                        // Split the method sig on spaces
                        methodbits = split(flattenWhiteSpace(msig), " ");

                        // Loop through those bits and pick out
                        // words we recognise. The first one that
                        // we don't is the method type, followed
                        // by the method name.
                        for (int z = 1; z < methodbits.length; z++)
                        {
                            if (methodbits[z].equals("static"))
                                isStatic = true;
                            else if (methodbits[z].equals("abstract"))
                                isAbstract = true;
                            else if (methodbits[z].equals("transient"))
                                isTransient = true;
                            else if (methodbits[z].equals("synchronized"))
                                isSynchronized = true;
                            else if (methodbits[z].equals("final"))
                                isFinal = true;
                            else
                            {
                                try
                                {
                                    // The next one must be the type
                                    mtype = methodbits[z];
                                    // And the name...
                                    mname = methodbits[z + 1];

                                    // Does the type contain a bracket?
                                    // if so, it's a constructor with
                                    // arguments.
                                    if (mtype.indexOf("(") != -1)
                                    {
                                        mtype = name;
                                        mname = name;
                                        isConstructor = true;
                                    }
                                    break;
                                }
                                catch (ArrayIndexOutOfBoundsException e)
                                {
                                    // We've run out of bits - this is
                                    // a constructor.
                                    isConstructor = true;
                                    mtype = name;
                                    mname = name;
                                    break;
                                }
                            }

                        }

                    }

                    if (!abort)
                    {

                        // Chop everything after that first bracket out of the method name
                        // if there is no bracket, then that's because they put a space after
                        // the method name and before the first bracket (which is ok)
                        try
                        {
                            mname = mname.substring(0, mname.indexOf("("));
                        }
                        catch (StringIndexOutOfBoundsException e)
                        {}
                    }

                    if (!abort)
                    {

                        // Enter another depth and output the operation
                        depth++;
						/*
                        System.out.println(getSpaces(depth) + "<UML:Operation visibility=\"" + lastAc + "\" " +
                                           "xmi.id=\"" + getXmiID() + "\" type=\"" + unqualifyType(asXMLAttribute(mtype)) + "\" " +
                                           "name=\"" + asXMLAttribute(mname) + "\"" +
                                           (isStatic ? " ownerScope=\"classifier\"" : "") +
                                           (isAbstract ? " isAbstract=\"true\"" : "") +
                                           ">");
										   */
						xmiCode=xmiCode+getSpaces(depth) + "<UML:Operation visibility=\"" + lastAc + "\" " +
                                           "xmi.id=\"" + getXmiID() + "\" type=\"" + unqualifyType(asXMLAttribute(mtype)) + "\" " +
                                           "name=\"" + asXMLAttribute(mname) + "\"" +
                                           (isStatic ? " ownerScope=\"classifier\"" : "") +
                                           (isAbstract ? " isAbstract=\"true\"" : "") +
                                           ">\n";

                        // Read the parameters
                        String params = msig.substring(msig.indexOf("(") + 1, msig.length());
                        String[] pbits = split(params, ",");
                        depth++;
                        for (int z = 0; z < pbits.length; z++)
                        {
                            try
                            {
                                String pb = pbits[z].trim();
                                String[] sp = split(pb, " ");
								/*
                                System.out.println(getSpaces(depth) + "<UML:Parameter " +
                                                   "visibility=\"" + lastAc + "\" xmi.id=\"" + getXmiID() + "\" " +
                                                   "value=\"\" type=\"" + unqualifyType(asXMLAttribute(sp[0])) +
                                                   "\" name=\"" + asXMLAttribute(sp[1]) + "\"/>");
												   */
								xmiCode=xmiCode+getSpaces(depth) + "<UML:Parameter " +
                                                   "visibility=\"" + lastAc + "\" xmi.id=\"" + getXmiID() + "\" " +
                                                   "value=\"\" type=\"" + unqualifyType(asXMLAttribute(sp[0])) +
                                                   "\" name=\"" + asXMLAttribute(sp[1]) + "\"/>\n";
								
                            }
                            catch (ArrayIndexOutOfBoundsException e)
                            {
                                // No params
                            }
                            catch (StringIndexOutOfBoundsException e)
                            {
                                // No params
                            }
                        }
                        depth--;

                        // Back up
                        //System.out.println(getSpaces(depth) + "</UML:Operation>");
						xmiCode=xmiCode+getSpaces(depth) + "</UML:Operation>\n";
                        depth--;
                    }
                }
                else
                {

                    // FIELD PARSER:
                    // ==============================================================

                    // Read the field signature
                    String fsig = "";
                    try
                    {
                        fsig = s.substring(pos, sigterminator).trim();
                    }
                    catch (StringIndexOutOfBoundsException e)
                    {
                        // This shouldn't ever happen
                        abort = true;
                        System.err.println("WARN: Couldn't find the end of the method sig - aborting: "
                                           + pos + "-" + sigterminator);
                    }

                    // Verify that the field start we found wasn't
                    // inside a string literal and some smart alec is
                    // running java2xmi over it's own source
                    if (s.substring(pos - 1, pos).equals("\""))
                    {
                        abort = true;
                        System.err.println("WARN: Almost confused by a string literal - aborting:\n  " + fsig);
                    }

                    if (!abort)
                    {

                        // Split the field sig on spaces
                        methodbits = split(flattenWhiteSpace(fsig), " ");

                        // Loop through those bits and pick out
                        // words we recognise. The first one that
                        // we don't is the field type, followed
                        // by the field name.
                        for (int z = 1; z < methodbits.length; z++)
                        {
                            if (methodbits[z].equals("static"))
                                isStatic = true;
                            else if (methodbits[z].equals("abstract"))
                                isAbstract = true;
                            else if (methodbits[z].equals("transient"))
                                isTransient = true;
                            else if (methodbits[z].equals("synchronized"))
                                isSynchronized = true;
                            else if (methodbits[z].equals("final"))
                                isFinal = true;
                            else if (methodbits[z].trim().equals(""))
                                isFinal = isFinal; // Ignore empty space
                            else
                            {
                                try
                                {
                                    // The next one must be the type
                                    mtype = methodbits[z];
                                    // And the name...
                                    mname = methodbits[z + 1];
                                    break;
                                }
                                catch (ArrayIndexOutOfBoundsException e)
                                {
                                    abort = true;
                                    System.err.println("WARN: Couldn't get enough parts for field type and name - aborting:\n " + fsig);
                                }
                            }

                        }
                    }

                    if (!abort)
                    {

                        // Chop everything after that first equals out of the field name
                        // if there is no equals, then that's because they put a space after
                        // the field name and before the equals (which is ok).
                        // Throw away upto the semicolon if we have one as well.
                        try
                        {
                            if (mname.indexOf("=") != -1)
                                mname = mname.substring(0, mname.indexOf("="));
                            else if (mname.indexOf(";") != -1)
                                mname = mname.substring(0, mname.indexOf(";"));
                        }
                        catch (StringIndexOutOfBoundsException e)
                        {}

                        // TODO: Maybe add support for extracting the initial value
                        // by looking at what's after the equals sign and before the
                        // semi-colon?

                    }

                    if (!abort)
                    {

                        // Enter another depth and output the attribute
                        depth++;
						/*
                        System.out.println(getSpaces(depth) + "<UML:Attribute visibility=\"" + lastAc + "\" " +
                                           "xmi.id=\"" + getXmiID() + "\" type=\"" + unqualifyType(asXMLAttribute(mtype)) + "\" " +
                                           "name=\"" + asXMLAttribute(mname) + "\"" +
                                           (isStatic ? " ownerScope=\"classifier\"" : "") +
                                           "/>");
										   */
						xmiCode=xmiCode+getSpaces(depth) + "<UML:Attribute visibility=\"" + lastAc + "\" " +
                                           "xmi.id=\"" + getXmiID() + "\" type=\"" + unqualifyType(asXMLAttribute(mtype)) + "\" " +
                                           "name=\"" + asXMLAttribute(mname) + "\"" +
                                           (isStatic ? " ownerScope=\"classifier\"" : "") +
                                           "/>\n";
                        depth--;
                    }
                }

                // Look for a public method/field again
                pos = findNextAccessor(s, pos + 1);
            }
        }
        catch (Exception e)
        {
            System.err.println("Exception occurred, abandoning class parse: " + e.getMessage());
        }

        // Output the closer for the class/interface and move back
        // up a depth level.
        if (wroteHeader)
        {
            if (isInterface)
			{
                //System.out.println(getSpaces(depth) + "</UML:Interface>");
				xmiCode=xmiCode+"</UML:Interface>\n";
			}
            else
			{
                //System.out.println(getSpaces(depth) + "</UML:Class>");
				xmiCode=xmiCode+getSpaces(depth) + "</UML:Class>\n";
			}
			
            depth--;
        }

		return(xmiCode);
		
    }//}}}

    public int getNextWhitespaceChar(String findin, int start)//{{{
    /**
     * Finds the next line break/space character in the given string
     * from the given position.
     */
    {
        int i = start;
        while (i < findin.length())
        {
            if (findin.substring(i, i + 1).equals( new String(new byte[] { 13 })))
                return i;
            else if (findin.substring(i, i + 1).equals( new String(new byte[] { 10 })))
                return i;
            else if (findin.substring(i, i + 1).equals(" "))
                return i;
            i++;
        }
        return -1;
    }//}}}

    public String unqualifyType(String type)//{{{
    /**
     * Given a Java type, unqualifies (removes the package) from
     * the class name.
     * @param type The type to unqualify
     * @return the unqualified class name
     */
    {
        // Do nothing if no package
        int lastDot = type.lastIndexOf(".");
        if (lastDot == -1)
            return type;
        else
            return type.substring(lastDot + 1, type.length());
    }//}}}

    public String flattenWhiteSpace(String in)//{{{
    /**
     * Given a string, loops through it and converts multiple
     * spaces/line breaks to one single space.
     */
    {
        StringBuffer o = new StringBuffer(in.length());
        boolean lastCharWasSpace = false;
        boolean outputOneSpace = false;
        for (int i = 0; i < in.length(); i++)
        {

            // Space or line break qualify as whitespace
            if (in.substring(i, i+1).equals(" "))
            {
                lastCharWasSpace = true;
            }
            else if (in.substring(i, i+1).equals("\n"))
            {
                lastCharWasSpace = true;
            }
            // If the char isn't one, append it and flag
            // it as such
            else
            {
                o.append(in.substring(i, i+1));
                lastCharWasSpace = false;
                outputOneSpace = false;
            }
            if (lastCharWasSpace && !outputOneSpace)
            {
                o.append(" ");
                outputOneSpace = true;
            }
        }
        return o.toString();
    }//}}}

    public int findNextAccessor(String in, int pos)//{{{
    /**
     * Finds the next accessor in a given string
     * An accessor is one of public/private/protected
     * @param in the string to find in
     * @param pos the position to start at
     * @return the position of the next accessor, or -1 if none was found
     */
    {

        int pu = in.indexOf("public ", pos);
        int pr = in.indexOf("private ", pos);
        int pt = in.indexOf("protected ", pos);

        // If private/protected accessors are turned off, pretend we
        // didn't find any
        if (noprivate)
            pr = 99999;
        if (noprotected)
            pt = 99999;

        // Translate -1s to 99999 to effectively ignore
        if (pu == -1)
            pu = 99999;
        if (pr == -1)
            pr = 99999;
        if (pt == -1)
            pt = 99999;

        int lowest = 99999;
        lastAc = "none";
        if (pu < lowest)
        {
            lowest = pu;
            lastAc = "public";
        }
        if (pr < lowest)
        {
            lowest = pr;
            lastAc = "private";
        }
        if (pt < lowest)
        {
            lowest = pt;
            lastAc = "protected";
        }

        if (lowest == 99999)
            return -1;
        else
            return lowest;
    }//}}}

    public String stripComments(String filename, String s)//{{{
     /**
     * Removes all C-Style java comments from a piece
     * of code.
     * @param s The code to look for comments in
     * @return The code without any comments
     */
   {

        StringBuffer output = new StringBuffer(s.length());

        int f = 0;

        for (int i = 0; i < s.length()-1; i++)
        {
            if (s.substring(i, i+2).equals("/*"))
            {
                f = s.indexOf("*/", i + 1);
                if (f != -1)
                {
                    i = f;
                }
                else
                {
                    System.err.println("WARN: Oops no closing */ tag found after /* in " + filename);
                    i = s.length() - 1;
                }
            }

            if (s.substring(i, i+2).equals("//"))
            {
                f = s.indexOf("\n", i + 1);
                if (f != -1)
                {
                    i = f;
                }
                else
                {
                    System.err.println("WARN: Oops - no line break found after // in " + filename);
                    i = s.length() - 1;
                }
            }

            try
            {
                output.append(s.substring(i, i+1));
            }
            catch (StringIndexOutOfBoundsException e)
            {
                System.err.println("WARN: Error appending char whilst removing comments - " + e.getMessage());
            }
        }

        return output.toString();

    }//}}}

    public String asXMLAttribute(String v)//{{{
     /** A final check before a value goes into an XML attribute
     *  all XML-upsetting chars are removed.
     */
   {
        v = v.replace('"', ' ');
        v = v.replace('&', ' ');
        return v.trim();
    }//}}}

    public int getXmiID()//{{{
     /** Returns the next unique ID for use with xmi.id tags */
   {
        nextID++;
        return nextID;
    }//}}}

    public void outputHeader()//{{{
     /**
     * Outputs the document header
     */
   {
        String s = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                   "<XMI xmlns:UML=\"org.omg/standards/UML\" verified=\"false\" timestamp=\"\" xmi.version=\"1.2\">\n" +
                   " <XMI.header>\n" +
                   "  <XMI.documentation>\n" +
                   "   <XMI.exporter>Java2XMI http://www.rawsontetley.org</XMI.exporter>\n" +
                   "   <XMI.exporterVersion>1.0</XMI.exporterVersion>\n" +
                   "   <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>\n" +
                   "  </XMI.documentation>\n" +
                   "  <XMI.model xmi.name=\"java2xmi\" href=\"\"/>\n" +
                   "  <XMI.metamodel xmi.name=\"UML\" xmi.version=\"1.3\" />\n" +
                   " </XMI.header>\n" +
                   " <XMI.content>\n" +
                   "  <UML:Model>\n" +
                   "   <UML:Stereotype visibility=\"public\" xmi.id=\"3\" name=\"datatype\" />\n" +
                   "   <UML:Stereotype visibility=\"public\" xmi.id=\"42\" name=\"interface\" />";

        System.out.println(s);
    }//}}}

    public void outputFooter()//{{{
     /**
     * Outputs the document footer
     */
   {
        String s = "  </UML:Model>\n" +
                   " </XMI.content>\n" +
                   "</XMI>";
        System.out.println(s);
    }//}}}

    public String readFileToString(File f)//{{{
     /**
     * Given a <code>File</code>, reads it into a single
     * String and returns it for parsing.
     *
     * @param f the file to read.
     */
   {

        try
        {
            FileInputStream in = new FileInputStream(f);
            byte[] buffer = new byte[in.available()];
            in.read(buffer);
            in.close();
            return new String(buffer);

        }
        catch (IOException e)
        {
            e.printStackTrace();
            return null;
        }
    }//}}}

    public static String[] split(String splitstring, String splitchar)//{{{
     /**
    * Splits a string by a particular char and returns an array of 
    * strings. If there are no occurrences of the split char, the
    * original string is returned in an array of 1 item.
    * @param splitstring The string to be split
    * @param splitchar The char to split on
    * @return An array of strings
    */
   {

        splitstring = splitstring.trim();

        // If there is only one element, just return that
        if (splitstring.indexOf(splitchar) == -1)
        {
            String[] rets = new String[1];
            rets[0] = splitstring;
            return rets;
        }

        // Find how many there are
        int tot = 0;
        int lpos = splitstring.indexOf(splitchar);
        while (lpos != -1)
        {
            tot++;
            lpos = splitstring.indexOf(splitchar, lpos + 1);
        }
        tot++;

        // Create our new array
        String[] rets = new String[tot];
        tot = 0;
        lpos = 0;
        int spos = splitstring.indexOf(splitchar);
        while (spos != -1)
        {
            // Add into the array
            rets[tot] = splitstring.substring(lpos, spos);
            tot++;
            lpos = spos + 1;
            spos = splitstring.indexOf(splitchar, lpos);
        }

        // Include last word
        rets[tot] = splitstring.substring(lpos, splitstring.length());

        // Return it
        return rets;
    }//}}}


}


More information about the umbrello mailing list