/* * Copyright (C) 2005, Intalio Inc. * * The program(s) herein may be used and/or copied only with the * written permission of Intalio Inc. or in accordance with the terms * and conditions stipulated in the agreement/contract under which the * program(s) have been supplied. * * $Id$ * * Created on Jan 12, 2005 by kvisco * */ package org.exolab.castor.util; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.text.ParseException; import java.util.ArrayList; import org.castor.xml.InternalContext; import org.castor.xml.XMLProperties; import org.exolab.castor.xml.Marshaller; import org.exolab.castor.xml.XMLContext; /** * A simple command line utility that parses Castor's change log file and outputs the * file in an XML format, a Castor mapping file may be used to change the XML format * that is output. Actually I haven't enabled any command line options yet, so the * mapping file can't be specified at the moment. * * @author <a href="mailto:kvisco@intalio.com">kvisco</a> * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $ */ public class ChangeLog2XML { /** * The default filename for the CHANGELOG file */ private static final String DEFAULT_FILE = "CHANGELOG"; private static final String DEFAULT_OUTPUT = "changelog.xml"; private static final String L_PAREN = "("; private static final String R_PAREN = ")"; private static final String DETAILS_TOKEN = "Details:"; private static final String VERSION_SEPARATOR = "---"; private static final String VERSION_TOKEN = "Version"; /** * The {@link AbstractInternalContext} holding global state and configuration * information. */ private InternalContext _internalContext; /** * Creates a new instance of ChangeLog2XML * */ public ChangeLog2XML() { super(); } /** * To set the {@link AbstractInternalContext} into the ChangeLog2XML instance. * @param internalContext the context to set */ public void setInternalContext(final InternalContext internalContext) { _internalContext = internalContext; } /** * The method which does the parsing of the CHANGELOG file * * @param file * @return * @throws FileNotFoundException * @throws IOException * @throws ParseException */ private Changelog parse(File file) throws FileNotFoundException, IOException, ParseException { if (!file.exists()) { throw new IllegalArgumentException("The argument 'file' must not be null!"); } FileReader fileReader = new FileReader(file); BufferedReader reader = new BufferedReader(fileReader); String line = null; boolean checkForVersion = false; boolean inEntry = false; String prevLine = null; StringBuffer buffer = null; String details = null; Changelog changelog = new Changelog(); Release release = null; while ((line = reader.readLine()) != null) { //-- check for version separator? if (checkForVersion) { checkForVersion = false; if (line.startsWith(VERSION_SEPARATOR)) { release = new Release(); String version = prevLine; //-- strip off 'Version' version = version.substring(VERSION_TOKEN.length()).trim(); release.setVersion(version); changelog.addRelease(release); continue; } inEntry = true; buffer = new StringBuffer(); buffer.append(prevLine.trim()); } //-- empty line is either end of entry or ignorable //-- whitespace if (line.length() == 0) { if (inEntry) { Entry entry = new Entry(); String value = buffer.toString(); /* cleanup of entry values*/ //-- strip off old entry designator "-"; if (value.startsWith("-")) { value = value.substring(1); } int idx = value.indexOf(':'); //-- Strip off component type (ie XML, JDO, ALL, etc); if ((idx >= 0) && (idx < 10)) { String component = value.substring(0, idx); entry.setComponent(component); value = value.substring(idx+1); } if (details != null) { entry.setDetails(details); } //-- check for committer and date int lastLength = prevLine.length(); if (prevLine.startsWith(L_PAREN) && prevLine.endsWith(R_PAREN)) { prevLine = prevLine.substring(1, lastLength-1); idx = prevLine.indexOf('-'); if (idx >= 0) { entry.setCommitter(prevLine.substring(0, idx).trim()); entry.setDate(prevLine.substring(idx+1).trim()); //-- cleanup value value = value.substring(0, value.length()-lastLength); } } entry.setValue(value.trim()); release.addEntry(entry); inEntry = false; details = null; } continue; } if (!inEntry) { if (line.startsWith(VERSION_TOKEN)) { checkForVersion = true; prevLine = line; continue; } inEntry = true; buffer = new StringBuffer(); buffer.append(line.trim()); } else { line = line.trim(); if (line.startsWith(DETAILS_TOKEN)) { details = line.substring(DETAILS_TOKEN.length() + 1); } else { if (buffer.length() > 0) { buffer.append(' '); } buffer.append(line); } prevLine = line; } //-- if we make it here we have valid text } fileReader.close(); return changelog; } public static void main(String[] args) { //TODO: add CommandLineOptions // options needed // 1. filename/path of CHANGELOG // 2. mapping file for customization // 3. output file name XMLContext xmlContext = new XMLContext(); ChangeLog2XML parser = xmlContext.createChangeLog2XML(); try { File file = new File(DEFAULT_FILE); Changelog changelog = parser.parse(file); file = new File(DEFAULT_OUTPUT); FileWriter writer = new FileWriter(file); xmlContext.setProperty(XMLProperties.USE_INDENTATION, true); Marshaller marshaller = xmlContext.createMarshaller(); marshaller.setWriter(writer); marshaller.setRootElement("changelog"); marshaller.setSuppressXSIType(true); marshaller.marshal(changelog); } catch(Exception ex) { ex.printStackTrace(); } } /* Inner JavaBean classes, these classes must follow the basic JavaBean guidelines so that the Castor Introspector will introspect them properly */ public static class Changelog { private ArrayList _releases = new ArrayList(); public Changelog() { super(); } public void addRelease(Release release) { if (release != null) { _releases.add(release); } } public Release[] getRelease() { Release[] relArray = new Release[_releases.size()]; _releases.toArray(relArray); return relArray; } } public static class Release { private String _version = null; private ArrayList _entries = new ArrayList(); public Release() { super(); } public void addEntry(Entry entry) { if (entry != null) { _entries.add(entry); } } public Entry[] getEntry() { Entry[] entryArray = new Entry[_entries.size()]; _entries.toArray(entryArray); return entryArray; } public String getVersion() { return _version; } public void setVersion(String version) { _version = version; } } public static class Entry { private String _component = null; private String _details = null; private String _value = null; private String _committer = null; private String _date = null; public Entry() { super(); } public String getCommitter() { return _committer; } public String getComponent() { return _component; } public String getDate() { return _date; } public String getDetails() { return _details; } public String getValue() { return _value; } public void setCommitter(String committer) { _committer = committer; } public void setComponent(String component) { _component = component; } public void setDate(String date) { _date = date; } public void setDetails(String details) { _details = details; } public void setValue(String value) { _value = value; } } }