001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU General
007: * Public License Version 2 only ("GPL") or the Common Development and Distribution
008: * License("CDDL") (collectively, the "License"). You may not use this file except in
009: * compliance with the License. You can obtain a copy of the License at
010: * http://www.netbeans.org/cddl-gplv2.html or nbbuild/licenses/CDDL-GPL-2-CP. See the
011: * License for the specific language governing permissions and limitations under the
012: * License. When distributing the software, include this License Header Notice in
013: * each file and include the License file at nbbuild/licenses/CDDL-GPL-2-CP. Sun
014: * designates this particular file as subject to the "Classpath" exception as
015: * provided by Sun in the GPL Version 2 section of the License file that
016: * accompanied this code. If applicable, add the following below the License Header,
017: * with the fields enclosed by brackets [] replaced by your own identifying
018: * information: "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Contributor(s):
021: *
022: * The Original Software is NetBeans. The Initial Developer of the Original Software
023: * is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun Microsystems, Inc. All
024: * Rights Reserved.
025: *
026: * If you wish your version of this file to be governed by only the CDDL or only the
027: * GPL Version 2, indicate your decision by adding "[Contributor] elects to include
028: * this software in this distribution under the [CDDL or GPL Version 2] license." If
029: * you do not indicate a single choice of license, a recipient has the option to
030: * distribute your version of this file under either the CDDL, the GPL Version 2 or
031: * to extend the choice of license to its licensees as provided above. However, if
032: * you add GPL Version 2 code and therefore, elected the GPL Version 2 license, then
033: * the option applies only if the new code is made subject to such option by the
034: * copyright holder.
035: */
036:
037: package org.netbeans.installer.infra.utils.comment.handlers;
038:
039: import org.netbeans.installer.infra.utils.comment.utils.Utils;
040: import java.io.File;
041: import java.io.IOException;
042: import java.util.regex.Matcher;
043: import java.util.regex.Pattern;
044:
045: /**
046: * The base class for ahndling file types in which block comments are used, such as
047: * java source files or xml documents.
048: *
049: * @author Kirill Sorokin
050: */
051: public abstract class BlockFileHandler implements FileHandler {
052: /////////////////////////////////////////////////////////////////////////////////
053: // Instance
054: /**
055: * The regular expression pattern which matches the initial comment.
056: */
057: protected final Pattern commentPattern;
058:
059: /**
060: * The comment opening string.
061: */
062: protected final String commentStart;
063:
064: /**
065: * The prefix which should be used for each line in the comment. If there should
066: * be no prefix - an empty line should be used.
067: */
068: protected final String commentPrefix;
069:
070: /**
071: * The comment closing string.
072: */
073: protected final String commentEnd;
074:
075: /**
076: * The cached file contents.
077: */
078: protected String contents;
079:
080: // constructor //////////////////////////////////////////////////////////////////
081: /**
082: * The constructor which should be called by the extending classes. It merely
083: * sets the class fields, performnig some basic validation.
084: *
085: * @param commentPattern The regular expression pattern which matches the
086: * initial comment.
087: * @param commentStart The comment opening string.
088: * @param commentPrefix The prefix which should be used for each line in the
089: * comment.
090: * @param commentEnd The comment closing string.
091: * @throws java.lang.IllegalArgumentException if the parameters validation
092: * fails.
093: */
094: protected BlockFileHandler(final Pattern commentPattern,
095: final String commentStart, final String commentPrefix,
096: final String commentEnd) {
097: if (commentPattern == null) {
098: throw new IllegalArgumentException(
099: "The 'commentPattern' parameter cannot be null."); // NOI18N
100: }
101: this .commentPattern = commentPattern;
102:
103: if (commentStart == null) {
104: throw new IllegalArgumentException(
105: "The 'commentStart' parameter cannot be null."); // NOI18N
106: }
107: this .commentStart = commentStart;
108:
109: if (commentPrefix == null) {
110: throw new IllegalArgumentException(
111: "The 'commentPrefix' parameter cannot be null."); // NOI18N
112: }
113: this .commentPrefix = commentPrefix;
114:
115: if (commentEnd == null) {
116: throw new IllegalArgumentException(
117: "The 'commentEnd' parameter cannot be null."); // NOI18N
118: }
119: this .commentEnd = commentEnd;
120: }
121:
122: // public ///////////////////////////////////////////////////////////////////////
123: /**
124: * {@inheritDoc}
125: */
126: final public void load(final File file) throws IOException {
127: if (file == null) {
128: throw new IllegalArgumentException(
129: "The 'file' parameter cannot be null."); // NOI18N
130: }
131:
132: contents = Utils.readFile(file);
133: }
134:
135: /**
136: * {@inheritDoc}
137: */
138: final public void save(final File file) throws IOException {
139: if (file == null) {
140: throw new IllegalArgumentException(
141: "The 'file' parameter cannot be null."); // NOI18N
142: }
143: if (contents == null) {
144: throw new IllegalStateException(
145: "The contents cache has not been intialized."); // NOI18N
146: }
147:
148: Utils.writeFile(file, contents);
149: }
150:
151: /**
152: * {@inheritDoc}
153: */
154: final public String getCurrentComment() {
155: if (contents == null) {
156: throw new IllegalStateException(
157: "The contents cache has not been intialized."); // NOI18N
158: }
159:
160: final Matcher matcher = commentPattern.matcher(contents);
161:
162: if (matcher.find()) {
163: return matcher.group(1);
164: } else {
165: return null;
166: }
167: }
168:
169: /**
170: * {@inheritDoc}
171: */
172: final public String getCorrectComment(final String text,
173: final int lineLength) {
174: return commentStart
175: + Utils.reformat(text, commentPrefix, lineLength)
176: + commentEnd + Utils.NL;
177: }
178:
179: /**
180: * {@inheritDoc}
181: */
182: final public void insertComment(final String text,
183: final int lineLength) {
184: if (text == null) {
185: throw new IllegalArgumentException(
186: "The 'text' parameter cannot be null."); // NOI18N
187: }
188: if (lineLength <= 0) {
189: throw new IllegalArgumentException(
190: "The 'lineLength' parameter must be positive."); // NOI18N
191: }
192: if (contents == null) {
193: throw new IllegalStateException(
194: "The contents cache has not been intialized."); // NOI18N
195: }
196:
197: final String comment = getCorrectComment(text, lineLength);
198: final int position = getCommentPosition();
199:
200: final String prefix = contents.substring(0, position);
201: final String suffix = contents.substring(position);
202:
203: contents = prefix + comment + suffix;
204: }
205:
206: /**
207: * {@inheritDoc}
208: */
209: final public void updateComment(final String text,
210: final int lineLength) {
211: if (text == null) {
212: throw new IllegalArgumentException(
213: "The 'text' parameter cannot be null."); // NOI18N
214: }
215: if (lineLength <= 0) {
216: throw new IllegalArgumentException(
217: "The 'lineLength' parameter must be positive."); // NOI18N
218: }
219: if (contents == null) {
220: throw new IllegalStateException(
221: "The contents cache has not been intialized."); // NOI18N
222: }
223:
224: final String currentComment = getCurrentComment();
225:
226: if (currentComment == null) {
227: insertComment(text, lineLength);
228: return;
229: }
230:
231: final String correctComment = getCorrectComment(text,
232: lineLength);
233:
234: final String prefix = contents.substring(0, contents
235: .indexOf(currentComment));
236: final String suffix = contents.substring(prefix.length()
237: + currentComment.length());
238:
239: contents = prefix + correctComment + suffix;
240: }
241:
242: // protected ////////////////////////////////////////////////////////////////////
243: /**
244: * Calculates the proper initial comment position. This is used in the
245: * <code>insertComment</code> method to devise the position at which to insert
246: * the new comment. Extending classes may want to override this method to
247: * provide initial comment position that is correct for their file type (e.g. in
248: * xml documents the comment should appear only after the
249: * <code><?xml ... ?></code> tag.
250: *
251: * @return The proper position for the initial comment.
252: */
253: protected int getCommentPosition() {
254: if (contents == null) {
255: throw new IllegalStateException(
256: "The contents cache has not been intialized."); // NOI18N
257: }
258:
259: return 0;
260: }
261: }
|