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
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.php.docgen;
042:
043: import java.io.BufferedWriter;
044: import java.io.File;
045: import java.io.FileWriter;
046: import java.io.IOException;
047: import java.util.regex.Matcher;
048: import java.util.regex.Pattern;
049:
050: /**
051: * @author ads
052: *
053: */
054: class CategoryParser {
055:
056: public static final String INDEX = "index"; // NOI18N
057:
058: private static final Pattern CATEGORY_PATTERN = Pattern.compile(
059: "<[ \t]*a[ \t]+name[ \t]*=[ \t]*['\"]?ref\\.",
060: Pattern.CASE_INSENSITIVE); // NOI18N
061:
062: private static final Pattern CATEGORY_NAME_PATTERN = Pattern
063: .compile(
064: "<[ \t]*h1[ \t]+class[^>]*>([^<]*)<\\/[ \t]*h1[ \t]*>",
065: Pattern.CASE_INSENSITIVE); // NOI18N
066:
067: private static final Pattern FUNCTION_ID_PATTERN = Pattern.compile(
068: "<[ \t]*a[ \t]+name[ \t]*=[ \t]*['\"]?function\\.",
069: Pattern.CASE_INSENSITIVE); // NOI18N
070:
071: private static final String CONTENT = "content.html"; // NOI18N
072:
073: private static final String NAME = "name"; // NOI18N
074:
075: CategoryParser(String category, int index, File folder) {
076: myContent = category;
077: myIndex = index;
078: myFolder = folder;
079: }
080:
081: void parse() throws WriteException {
082: Matcher matcher = CATEGORY_PATTERN.matcher(getContent());
083: if (!matcher.find()) {
084: throw new IllegalStateException("Cannot identify category "
085: + myIndex); // NOI18N
086: }
087: int index = matcher.end();
088: int end = getContent().indexOf(CategoriesParser.CLOSE_BRACKET,
089: index);
090: String id = extractName(getContent(), index, end);
091: File file = new File(getFolder(), id);
092: file.mkdirs();
093: saveContent(file);
094: saveName(file, index);
095:
096: appendToIndex(id);
097:
098: parseFunctions(file, index);
099: }
100:
101: private void appendToIndex(String id) throws WriteException {
102: File indexFile = new File(getFolder(), INDEX);
103: BufferedWriter writer = null;
104: try {
105: writer = new BufferedWriter(new FileWriter(indexFile, true));
106: writer.write(id);
107: writer.write('\n');
108: } catch (IOException e) {
109: throw new WriteException("Couldn't write to index file", e);
110: } finally {
111: if (writer != null) {
112: try {
113: writer.close();
114: } catch (IOException e) {
115: throw new WriteException(
116: "Couldn't close index file", e);
117: }
118: }
119: }
120: }
121:
122: private void parseFunctions(File file, int index)
123: throws WriteException {
124: String content = getContent().substring(index);
125: Matcher matcher = FUNCTION_ID_PATTERN.matcher(content);
126: int previousStart = -1;
127: String nameId = null;
128: String methodContent = null;
129:
130: while (matcher.find()) {
131: int start = matcher.end();
132: int patternEnd = content.indexOf(
133: CategoriesParser.CLOSE_BRACKET, start);
134: String namePretender = extractName(content, start,
135: patternEnd);
136: if (namePretender.contains(".")) {
137: continue;
138: }
139: if (previousStart > 0) {
140: int end = matcher.start();
141: methodContent = content.substring(previousStart, end);
142: MethodParser parser = new MethodParser(nameId,
143: methodContent, file);
144: parser.parse();
145:
146: }
147: nameId = namePretender;
148: previousStart = patternEnd + 1;
149: }
150:
151: /*
152: * Handle last function in category.
153: */
154: if (previousStart > 0) {
155: methodContent = content.substring(previousStart);
156: MethodParser parser = new MethodParser(nameId,
157: methodContent, file);
158: parser.parse();
159: }
160: }
161:
162: private String extractName(String content, int start, int patternEnd) {
163: String name = content.substring(start, patternEnd).trim();
164: if (name.endsWith("'") || name.endsWith("\"")) {
165: name = name.substring(0, name.length() - 1);
166: }
167: return name;
168: }
169:
170: private void saveName(File categoryDir, int index)
171: throws WriteException {
172: Matcher matcher = CATEGORY_NAME_PATTERN.matcher(getContent()
173: .substring(index));
174: if (!matcher.find()) {
175: throw new IllegalStateException("Cannot identify category "
176: + myIndex); // NOI18N
177: }
178:
179: String name = matcher.group(1);
180:
181: File file = new File(categoryDir, NAME);
182: BufferedWriter writer = null;
183: try {
184: writer = new BufferedWriter(new FileWriter(file));
185: writer.write(name);
186: } catch (IOException e) {
187: throw new WriteException("Couldn't write file " + file, e);
188: } finally {
189: if (writer != null) {
190: try {
191: writer.close();
192: } catch (IOException e) {
193: e.printStackTrace();
194: }
195: }
196: }
197: }
198:
199: private void saveContent(File categoryDir) throws WriteException {
200: File file = new File(categoryDir, CONTENT);
201: BufferedWriter writer = null;
202: try {
203: writer = new BufferedWriter(new FileWriter(file));
204: writer.write(getContent());
205: } catch (IOException e) {
206: throw new WriteException("Couldn't write file " + file, e);
207: } finally {
208: if (writer != null) {
209: try {
210: writer.close();
211: } catch (IOException e) {
212: throw new WriteException("Couldn't close file "
213: + file, e);
214: }
215: }
216: }
217: }
218:
219: private File getFolder() {
220: return myFolder;
221: }
222:
223: private String getContent() {
224: return myContent;
225: }
226:
227: private String myContent;
228:
229: private int myIndex;
230:
231: private File myFolder;
232: }
|