/* * Rapid Beans Framework, SDK, Ant Tasks: CodeFile.java * * Copyright (C) 2009 Martin Bluemel * * Creation Date: 10/29/2005 * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU Lesser General Public License as published by the Free Software Foundation; * either version 3 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. * You should have received a copies of the GNU Lesser General Public License and the * GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. */ package org.rapidbeans.maven.generator.utils; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.rapidbeans.maven.exceptions.BuildException; /** * code file. * * @version initial * * @author Martin Bluemel */ public abstract class CodeFile { /** * handle for the code file's physical file. */ private File file = null; /** * getter for the file. * * @return the file */ public final File getFile() { return this.file; } /** * the code file's parts. */ private List<CodeFilePart> parts = null; /** * getter. * * @return the parts list */ public final List<CodeFilePart> getParts() { return this.parts; } /** * the code bodie's map. */ private HashMap<String, CodeFilePartBody> bodies = null; /** * retrieves the body with the appropriate signature. * * @param signature * the signature * @return the body part */ public final CodeFilePartBody getBody(final String signature) { return this.bodies.get(signature); } /** * append a part. * * @param part * the part */ public final void appendPart(final CodeFilePart part) { this.parts.add(part); } /** * append a part. * * @param part * the part */ public final void appendBodyPart(final CodeFilePartBody part) { this.parts.add(part); this.bodies.put(part.getSignature(), part); } /** * parser stae: basic. */ private static final int STATE_BASIC = 0; /** * parser state: at the begin of a code body. */ private static final int STATE_BEGIN_MANCODE_BODY = 1; /** * parser stae: within code body. */ private static final int STATE_MANCODE_BODY = 2; /** * validation. */ protected abstract void validate(); /** * parse the file. * * @param oneLineComment * combination of character to mark a one line comment * @param beginSection * text of line (comment) that marks the begin of a manually * coded section. * @param endSection * text of line (comment) that marks the end of a manually coded * section * @throws IOException * I/O problem */ public final void parse(final String oneLineComment, final String beginSection, final String endSection) throws IOException { final String beginSectionComment = oneLineComment + " " + beginSection; final String endSectionComment = oneLineComment + " " + endSection; final LineNumberReader reader = new LineNumberReader(new FileReader(this.getFile())); String line, trimmedLine, signature; CodeFilePartBody body = null; int state = 0; while ((line = reader.readLine()) != null) { trimmedLine = line.trim(); switch (state) { case STATE_BASIC: if (trimmedLine.startsWith(beginSectionComment)) { body = new CodeFilePartBody(line); state = STATE_BEGIN_MANCODE_BODY; } else { appendPart(new CodeFilePartLine(line)); state = STATE_BASIC; } break; case STATE_BEGIN_MANCODE_BODY: signature = stripOneLineComment(trimmedLine); body.setBeginCommentSignature(line); body.setSignature(signature); state = STATE_MANCODE_BODY; break; case STATE_MANCODE_BODY: if (trimmedLine.startsWith(endSectionComment)) { body.setEndComment(line); this.appendBodyPart(body); state = STATE_BASIC; } else { body.appendLine(line); state = STATE_MANCODE_BODY; } break; default: throw new BuildException("Parser error: wrong state: " + Integer.toString(state)); } } reader.close(); } /** * constructor. * * @param argFile * the file */ public CodeFile(final File argFile) { this.file = argFile; this.validate(); this.parts = new ArrayList<CodeFilePart>(); this.bodies = new HashMap<String, CodeFilePartBody>(); } /** * default strip characters (whitespace). */ private static final char[] STRIP_CHARS_ONE_LINE_COMMENT = { ' ', '\t', '/' }; /** * strips " // xxx yyy" to "xxx yyy". * * @param s * the input string * @return the stripped string */ private static String stripOneLineComment(final String s) { return StringHelper.strip(s, STRIP_CHARS_ONE_LINE_COMMENT, StripMode.leading); } }