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.vmd.api.codegen;
042:
043: import org.netbeans.api.editor.guards.GuardedSection;
044: import org.netbeans.api.editor.guards.GuardedSectionManager;
045: import org.netbeans.modules.vmd.api.model.DesignDocument;
046: import org.netbeans.modules.vmd.api.model.common.DocumentSupport;
047: import org.openide.ErrorManager;
048: import org.openide.text.NbDocument;
049:
050: import javax.swing.text.BadLocationException;
051: import javax.swing.text.StyledDocument;
052: import java.util.ArrayList;
053: import java.util.Collection;
054: import java.util.HashMap;
055: import java.util.WeakHashMap;
056:
057: /**
058: * @author David Kaspar
059: */
060: public final class JavaCodeGenerator {
061:
062: private static final JavaCodeGenerator DEFAULT = new JavaCodeGenerator();
063:
064: public static final String VMD_FIELDS_SECTION_ID = "fields"; // NOI18N
065: public static final String VMD_METHODS_SECTION_ID = "methods"; // NOI18N
066:
067: // document -> a map from editableid to usercode
068: // put into the properites of styleddocument
069: private final WeakHashMap<StyledDocument, HashMap<String, String>> userCodes = new WeakHashMap<StyledDocument, HashMap<String, String>>();
070:
071: private final HashMap<StyledDocument, ArrayList<String>> usedMultiSectionIDs = new HashMap<StyledDocument, ArrayList<String>>();
072:
073: public static JavaCodeGenerator getDefault() {
074: return DEFAULT;
075: }
076:
077: private JavaCodeGenerator() {
078: }
079:
080: public void updateUserCodesFromEditor(final StyledDocument document) {
081: NbDocument.runAtomic(document, new Runnable() {
082: public void run() {
083: updateUserCodesFromEditorCore(document);
084: }
085: });
086: }
087:
088: public void generateCode(final StyledDocument document,
089: final DesignDocument designDocument) {
090: final Collection<CodePresenter> presenters = DocumentSupport
091: .gatherAllPresentersOfClass(designDocument,
092: CodePresenter.class);
093: try {
094: NbDocument.runAtomic(document, new Runnable() {
095: public void run() {
096: generateCodeCore(presenters, document);
097: }
098: });
099: } finally {
100: usedMultiSectionIDs.remove(document);
101: }
102:
103: Collection<CodeGlobalLevelPresenter> globalLevel = DocumentSupport
104: .filterPresentersForClass(presenters,
105: CodeGlobalLevelPresenter.class);
106: for (CodeGlobalLevelPresenter presenter : globalLevel)
107: presenter.performGlobalGeneration(document);
108: }
109:
110: private void generateCodeCore(Collection<CodePresenter> presenters,
111: StyledDocument document) {
112: Collection<CodeClassLevelPresenter> classLevel = DocumentSupport
113: .filterPresentersForClass(presenters,
114: CodeClassLevelPresenter.class);
115:
116: MultiGuardedSection section;
117:
118: section = MultiGuardedSection.create(document,
119: VMD_FIELDS_SECTION_ID);
120: assert section != null;
121: section
122: .getWriter()
123: .write(
124: "//<editor-fold defaultstate=\"collapsed\" desc=\" Generated Fields \">\n"); // NOI18N
125: for (CodeClassLevelPresenter presenter : classLevel)
126: presenter.generateFieldSectionCode(section);
127: section.getWriter().write("//</editor-fold>\n"); // NOI18N
128: section.getWriter().commit();
129: section.close();
130:
131: section = MultiGuardedSection.create(document,
132: VMD_METHODS_SECTION_ID);
133: section
134: .getWriter()
135: .write(
136: "//<editor-fold defaultstate=\"collapsed\" desc=\" Generated Methods \">\n"); // NOI18N
137: for (CodeClassLevelPresenter presenter : classLevel)
138: presenter.generateMethodSectionCode(section);
139: section.getWriter().write("//</editor-fold>\n"); // NOI18N
140: section.getWriter().commit();
141: section.close();
142:
143: for (CodeClassLevelPresenter presenter : classLevel)
144: presenter.generateClassBodyCode(document);
145:
146: removeUnusedSections(document);
147: }
148:
149: private HashMap<String, String> getEditableUserCodes(
150: StyledDocument document) {
151: assert document != null;
152: HashMap<String, String> codes = userCodes.get(document);
153: if (codes == null) {
154: codes = new HashMap<String, String>();
155: userCodes.put(document, codes);
156: }
157: return codes;
158: }
159:
160: String getUserCode(StyledDocument document, String multiGuardedID,
161: String editableID) {
162: HashMap<String, String> editableUserCodes = getEditableUserCodes(document);
163: return editableUserCodes.get(multiGuardedID + "|" + editableID); // NOI18N
164: }
165:
166: public void putUserCode(StyledDocument document,
167: String multiGuardedID, String editableID, String userCode) {
168: HashMap<String, String> editableUserCodes = getEditableUserCodes(document);
169: editableUserCodes.put(multiGuardedID + "|" + editableID,
170: userCode); // NOI18N
171: }
172:
173: private void updateUserCodesFromEditorCore(StyledDocument document) {
174: for (GuardedSection section : GuardedSectionManager
175: .getInstance(document).getGuardedSections()) {
176: if (!MultiGuardedSection
177: .isPartOfMultiGuardedSection(section))
178: continue;
179:
180: Object[] info = MultiGuardedSection
181: .parsePartOfMultiGuardedSection(section);
182: GuardedSection nextSection = MultiGuardedSection
183: .findNextPartOfMultiGuardedSectionAfter(document,
184: info);
185: if (nextSection == null)
186: continue;
187:
188: try {
189: int begin = section.getEndPosition().getOffset() + 1;
190: int end = nextSection.getStartPosition().getOffset();
191: String userCode = document.getText(begin, end - begin);
192: putUserCode(document, (String) info[0],
193: (String) info[2], userCode);
194: } catch (BadLocationException e) {
195: ErrorManager.getDefault().notify(e);
196: }
197: }
198: }
199:
200: private void removeUnusedSections(StyledDocument document) {
201: Iterable<GuardedSection> allSections = GuardedSectionManager
202: .getInstance(document).getGuardedSections();
203: ArrayList<String> toDoIDs = new ArrayList<String>();
204:
205: for (GuardedSection section : allSections) {
206: if (MultiGuardedSection
207: .isPartOfMultiGuardedSection(section)) {
208: if (!isMultiSectionUsed(document, section)) {
209: Object[] objects = MultiGuardedSection
210: .parsePartOfMultiGuardedSection(section);
211: String id = (String) objects[0];
212: if (!toDoIDs.contains(id))
213: toDoIDs.add(id);
214: }
215: }
216: }
217:
218: for (String id : toDoIDs)
219: MultiGuardedSection.remove(document, id);
220: }
221:
222: private boolean isMultiSectionUsed(StyledDocument document,
223: GuardedSection section) {
224: ArrayList<String> multiGuardedIDs = usedMultiSectionIDs
225: .get(document);
226: return multiGuardedIDs != null
227: && multiGuardedIDs.contains(MultiGuardedSection
228: .parsePartOfMultiGuardedSection(section)[0]);
229: }
230:
231: void registerUsedMultiGuardedSection(StyledDocument document,
232: MultiGuardedSection section) {
233: ArrayList<String> multiSections = usedMultiSectionIDs
234: .get(document);
235: if (multiSections == null) {
236: multiSections = new ArrayList<String>();
237: usedMultiSectionIDs.put(document, multiSections);
238: }
239: multiSections.add(section.getMultiGuardedID());
240: }
241:
242: }
|