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: */package org.netbeans.modules.vmd.midp.converter.wizard;
041:
042: import com.sun.source.tree.ClassTree;
043: import com.sun.source.util.TreePath;
044: import org.netbeans.api.java.source.CompilationController;
045: import org.netbeans.api.java.source.JavaSource;
046: import org.netbeans.api.java.source.Task;
047: import org.netbeans.api.visual.widget.Widget;
048: import org.netbeans.api.project.FileOwnerQuery;
049: import org.netbeans.api.project.Project;
050: import org.netbeans.modules.vmd.api.flow.visual.FlowNodeDescriptor;
051: import org.netbeans.modules.vmd.api.flow.visual.FlowScene;
052: import org.netbeans.modules.vmd.api.flow.FlowSupport;
053: import org.netbeans.modules.vmd.api.io.providers.DocumentSerializer;
054: import org.netbeans.modules.vmd.api.io.providers.IOSupport;
055: import org.netbeans.modules.vmd.api.model.Debug;
056: import org.netbeans.modules.vmd.api.model.DesignComponent;
057: import org.netbeans.modules.vmd.api.model.DesignDocument;
058: import org.netbeans.modules.vmd.api.model.common.DocumentSupport;
059: import org.netbeans.modules.vmd.midp.components.MidpDocumentSupport;
060: import org.netbeans.modules.vmd.midp.components.MidpTypes;
061: import org.netbeans.modules.vmd.midp.components.categories.PointsCategoryCD;
062: import org.netbeans.modules.vmd.midp.components.general.ClassCD;
063: import org.netbeans.modules.vmd.midp.components.points.MobileDeviceCD;
064: import static org.netbeans.modules.vmd.midp.converter.wizard.ConverterUtil.getBoolean;
065: import org.netbeans.modules.mobility.project.J2MEProjectGenerator;
066: import org.netbeans.spi.project.support.ant.AntProjectHelper;
067: import org.openide.cookies.EditorCookie;
068: import org.openide.filesystems.FileObject;
069: import org.openide.filesystems.Repository;
070: import org.openide.loaders.DataFolder;
071: import org.openide.loaders.DataObject;
072: import org.openide.text.CloneableEditorSupport;
073: import org.openide.util.Exceptions;
074: import org.w3c.dom.Node;
075:
076: import javax.lang.model.element.TypeElement;
077: import javax.swing.*;
078: import javax.swing.text.BadLocationException;
079: import javax.swing.text.StyledDocument;
080: import java.util.ArrayList;
081: import java.util.HashMap;
082: import java.util.List;
083: import org.openide.util.NbBundle;
084:
085: /**
086: * @author David Kaspar
087: */
088: public class Converter {
089:
090: public static ArrayList<String> convert(
091: final FileObject inputJavaFile,
092: final FileObject inputDesignFile, String outputFileName) {
093: final ArrayList<String> errors = new ArrayList<String>();
094: try {
095: DataFolder folder = DataFolder.findFolder(inputJavaFile
096: .getParent());
097:
098: DataObject input = DataObject.find(inputJavaFile);
099: EditorCookie editorCookie = input
100: .getCookie(EditorCookie.class);
101: final StyledDocument styledDocument = editorCookie
102: .openDocument();
103:
104: final Node rootNode = XMLUtil.getRootNode(inputDesignFile);
105: if (!"1.3".equals(XMLUtil.getAttributeValue(rootNode,
106: "version"))) { // NOI18N
107: Debug.warning(NbBundle.getMessage(Converter.class,
108: "Convert.oldDesign.error")); // NOI18N
109: errors.add(NbBundle.getMessage(Converter.class,
110: "Convert.oldDesign.error")); // NOI18N
111: return errors;
112: }
113:
114: final List<ConverterItem> items = getConverterItems(rootNode);
115:
116: DataObject template = DataObject
117: .find(Repository
118: .getDefault()
119: .getDefaultFileSystem()
120: .findResource(
121: "Templates/MIDP/ConverterVisualMIDlet.java")); // NOI18N
122: final DataObject outputDesign = template
123: .createFromTemplate(folder, outputFileName);
124: DocumentSerializer serializer = IOSupport
125: .getDocumentSerializer(outputDesign);
126: serializer.waitDocumentLoaded();
127: final DesignDocument document = serializer.getDocument();
128:
129: EditorCookie outputEditorCookie = outputDesign
130: .getCookie(EditorCookie.class);
131: final StyledDocument outputStyledDocument = outputEditorCookie
132: .openDocument();
133:
134: ConverterCustom.loadItemsToRegistry(items, document);
135:
136: final HashMap<String, ConverterItem> id2item = new HashMap<String, ConverterItem>();
137: for (ConverterItem item : items)
138: id2item.put(item.getID(), item);
139:
140: document.getTransactionManager().writeAccess(
141: new Runnable() {
142: public void run() {
143: for (ConverterItem item : items)
144: convert(id2item, item, document);
145:
146: try {
147: ConverterCode.convertCode(items,
148: styledDocument,
149: outputStyledDocument, document,
150: inputJavaFile.getName(),
151: outputDesign.getPrimaryFile()
152: .getName());
153: } catch (BadLocationException e) {
154: Exceptions.printStackTrace(e);
155: }
156: }
157: });
158:
159: for (ConverterItem item : items)
160: if (!item.isUsed())
161: Debug.warning("Unrecognized component: "
162: + item.getTypeID()); // NOI18N
163:
164: // final Map<DesignComponent, Point> flowNodes = getFlowNodes (id2item, rootNode);
165: // if (! flowNodes.isEmpty ()) {
166: SwingUtilities.invokeAndWait(new Runnable() {
167: public void run() {
168: document.getTransactionManager().writeAccess(
169: new Runnable() {
170: public void run() {
171: FlowScene scene = FlowSupport
172: .getFlowSceneForDocument(document);
173: for (FlowNodeDescriptor node : scene
174: .getNodes()) {
175: // Point point = flowNodes.get (node.getRepresentedComponent ());
176: // if (point != null) {
177: // Widget widget = scene.findWidget (node);
178: // if (widget != null)
179: // widget.setPreferredLocation (point);
180: // }
181: Widget widget = scene
182: .findWidget(node);
183: if (widget != null)
184: widget
185: .setPreferredLocation(null);
186: }
187: }
188: });
189: }
190: });
191: // }
192:
193: IOSupport.forceUpdateCode(outputDesign);
194: CloneableEditorSupport cloneableEditorSupport = IOSupport
195: .getCloneableEditorSupport(outputDesign);
196: cloneableEditorSupport.saveDocument();
197: cloneableEditorSupport.close();
198:
199: final String[] classNames = new String[2];
200: JavaSource.forDocument(styledDocument).runUserActionTask(
201: new Task<CompilationController>() {
202: public void run(CompilationController parameter)
203: throws Exception {
204: parameter
205: .toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
206: ClassTree classTree = ConverterCode
207: .findMainClass(parameter);
208: TypeElement element = (TypeElement) parameter
209: .getTrees()
210: .getElement(
211: TreePath
212: .getPath(
213: parameter
214: .getCompilationUnit(),
215: classTree));
216: classNames[0] = element.getQualifiedName()
217: .toString();
218: }
219: }, true);
220: JavaSource.forDocument(outputStyledDocument)
221: .runUserActionTask(
222: new Task<CompilationController>() {
223: public void run(
224: CompilationController parameter)
225: throws Exception {
226: parameter
227: .toPhase(JavaSource.Phase.ELEMENTS_RESOLVED);
228: ClassTree classTree = ConverterCode
229: .findMainClass(parameter);
230: TypeElement element = (TypeElement) parameter
231: .getTrees()
232: .getElement(
233: TreePath
234: .getPath(
235: parameter
236: .getCompilationUnit(),
237: classTree));
238: classNames[1] = element
239: .getQualifiedName()
240: .toString();
241: }
242: }, true);
243:
244: Project project = FileOwnerQuery.getOwner(inputJavaFile);
245: if (project != null) {
246: AntProjectHelper helper = project.getLookup().lookup(
247: AntProjectHelper.class);
248: if (helper != null)
249: J2MEProjectGenerator.copyMIDletProperty(project,
250: helper, classNames[0], classNames[1]);
251: }
252: } catch (Exception e) {
253: Exceptions.printStackTrace(e);
254: }
255:
256: return errors;
257: }
258:
259: // private static Map<DesignComponent, Point> getFlowNodes (HashMap<String, ConverterItem> id2item, Node rootNode) {
260: // HashMap<DesignComponent, Point> map = new HashMap<DesignComponent, Point> ();
261: // Node flowNode = XMLUtil.getChild (rootNode, "FlowDocument"); // NOI18N
262: // String version = XMLUtil.getAttributeValue (flowNode, "version"); // NOI18N
263: // if (! "1.1".equals (version)) // NOI18N
264: // return Collections.emptyMap ();
265: // for (Node node : XMLUtil.getChildren (flowNode, "Node")) { // NOI18N
266: // String id = XMLUtil.getAttributeValue (node, "id"); // NOI18N
267: // ConverterItem item = id2item.get (id);
268: // if (item == null || ! item.isUsed ())
269: // continue;
270: // String loc = XMLUtil.getAttributeValue (node, "location"); // NOI18N
271: // int i = loc.indexOf (','); // NOI18N
272: // if (i < 0)
273: // continue;
274: // int x = Integer.parseInt (loc.substring (0, i));
275: // int y = Integer.parseInt (loc.substring (i + 1));
276: // map.put (item.getRelatedComponent (), new Point (x, y));
277: // }
278: // return map;
279: // }
280:
281: private static List<ConverterItem> getConverterItems(Node rootNode) {
282: ArrayList<ConverterItem> components = new ArrayList<ConverterItem>();
283: Node documentNode = XMLUtil
284: .getChild(rootNode, "DesignDocument"); // NOI18N
285: for (Node componentNode : XMLUtil.getChildren(documentNode,
286: "DesignComponent")) { // NOI18N
287: String typeid = XMLUtil.getAttributeValue(componentNode,
288: "typeid"); // NOI18N
289: typeid = convertTypeIDFromString(typeid);
290: ConverterItem item = new ConverterItem(XMLUtil
291: .getAttributeValue(componentNode, "uid"), // NOI18N
292: XMLUtil.getAttributeValue(componentNode, "id"), // NOI18N
293: typeid // NOI18N
294: );
295: for (Node propertyNode : XMLUtil.getChildren(componentNode,
296: "Property")) { // NOI18N
297: item.addProperty(XMLUtil.getAttributeValue(
298: propertyNode, "name"), // NOI18N
299: XMLUtil
300: .getAttributeValue(propertyNode,
301: "value") // NOI18N
302: );
303: }
304: for (Node containerPropertyNode : XMLUtil.getChildren(
305: componentNode, "ContainerProperty")) { // NOI18N
306: String name = XMLUtil.getAttributeValue(
307: containerPropertyNode, "name"); // NOI18N
308: item.initContainerProperty(name); // NOI18N
309: for (Node itemNode : XMLUtil.getChildren(
310: containerPropertyNode, "ContainerPropertyItem"))
311: // NOI18N
312: item.addContainerPropertyItem(name, XMLUtil
313: .getAttributeValue(itemNode, "value")); // NOI18N
314: }
315: components.add(item);
316: }
317: return components;
318: }
319:
320: private static String convertTypeIDFromString(String string) {
321: if (string == null)
322: return null;
323: int dimension = 0;
324: if (string.charAt(0) == '#') {
325: int pos = 1;
326: for (;;) {
327: char c;
328: if (pos >= string.length()) {
329: dimension = 0;
330: break;
331: }
332: c = string.charAt(pos++);
333: if (c == '#')
334: break;
335: if (!Character.isDigit(c)) {
336: dimension = 0;
337: break;
338: }
339: dimension = dimension * 10 + (c - '0');
340: }
341: if (dimension > 0)
342: string = string.substring(pos);
343: }
344: int i = string.indexOf(':');
345: return i >= 0 ? string.substring(i + 1) : string;
346: }
347:
348: private static void convert(HashMap<String, ConverterItem> id2item,
349: ConverterItem item, DesignDocument document) {
350: if (item.isUsed())
351: return;
352: String id = item.getID();
353: String typeID = item.getTypeID();
354:
355: if ("javax.microedition.lcdui.Command".equals(typeID)) // NOI18N
356: ConverterResources.convertCommand(item, document);
357:
358: else if ("javax.microedition.lcdui.Alert".equals(typeID)) // NOI18N
359: ConverterDisplayables.convertAlert(id2item, item, document);
360: else if ("javax.microedition.lcdui.Form".equals(typeID)) // NOI18N
361: ConverterDisplayables.convertForm(id2item, item, document);
362: else if ("javax.microedition.lcdui.List".equals(typeID)) // NOI18N
363: ConverterDisplayables.convertList(id2item, item, document);
364: else if ("javax.microedition.lcdui.TextBox".equals(typeID)) // NOI18N
365: ConverterDisplayables.convertTextBox(id2item, item,
366: document);
367:
368: else if ("javax.microedition.lcdui.ChoiceGroup".equals(typeID)) // NOI18N
369: ConverterItems.convertChoiceGroup(id2item, item, document);
370: else if ("javax.microedition.lcdui.DateField".equals(typeID)) // NOI18N
371: ConverterItems.convertDateField(id2item, item, document);
372: else if ("javax.microedition.lcdui.Gauge".equals(typeID)) // NOI18N
373: ConverterItems.convertGauge(id2item, item, document);
374: else if ("javax.microedition.lcdui.Gauge-AlertIndicator_Helper"
375: .equals(typeID)) // NOI18N
376: ConverterItems.convertAlertIndicator(id2item, item,
377: document);
378: else if ("javax.microedition.lcdui.ImageItem".equals(typeID)) // NOI18N
379: ConverterItems.convertImageItem(id2item, item, document);
380: else if ("javax.microedition.lcdui.Spacer".equals(typeID)) // NOI18N
381: ConverterItems.convertSpacer(id2item, item, document);
382: else if ("javax.microedition.lcdui.StringItem".equals(typeID)) // NOI18N
383: ConverterItems.convertStringItem(id2item, item, document);
384: else if ("javax.microedition.lcdui.TextField".equals(typeID)) // NOI18N
385: ConverterItems.convertTextField(id2item, item, document);
386:
387: else if ("javax.microedition.lcdui.Font".equals(typeID)) // NOI18N
388: ConverterResources.convertFont(item, document);
389: else if ("javax.microedition.lcdui.Ticker".equals(typeID)) // NOI18N
390: ConverterResources.convertTicker(item, document);
391: else if ("javax.microedition.lcdui.Image".equals(typeID)) // NOI18N
392: ConverterResources.convertImage(item, document);
393:
394: else if ("GROUP-org.netbeans.modules.mvd.model.midp2.Midp2ChoiceElementDC"
395: .equals(typeID)) // NOI18N
396: ConverterElements.convertChoiceElement(id2item, item,
397: document);
398: else if ("GROUP-org.netbeans.modules.mvd.model.midp2.Midp2ListElementDC"
399: .equals(typeID)) // NOI18N
400: ConverterElements.convertListElement(id2item, item,
401: document);
402:
403: else if ("org.netbeans.microedition.util.SimpleCancellableTask"
404: .equals(typeID)) // NOI18N
405: ConverterBuilt.convertSimpleCancellableTask(id2item, item,
406: document);
407: else if ("org.netbeans.microedition.lcdui.SimpleTableModel"
408: .equals(typeID)) // NOI18N
409: ConverterBuilt.convertSimpleTableModel(id2item, item,
410: document);
411: else if ("org.netbeans.microedition.lcdui.SplashScreen"
412: .equals(typeID)) // NOI18N
413: ConverterBuilt.convertSplashScreen(id2item, item, document);
414: else if ("org.netbeans.microedition.lcdui.TableItem"
415: .equals(typeID)) // NOI18N
416: ConverterBuilt.convertTableItem(id2item, item, document);
417: else if ("org.netbeans.microedition.lcdui.WaitScreen"
418: .equals(typeID)) // NOI18N
419: ConverterBuilt.convertWaitScreen(id2item, item, document);
420:
421: else if ("javax.microedition.m2g.SVGImage".equals(typeID)) // NOI18N
422: ConverterSVG.convertImage(id2item, item, document);
423: else if ("org.netbeans.microedition.svg.SVGAnimatorWrapper"
424: .equals(typeID)) // NOI18N
425: ConverterSVG.convertPlayer(id2item, item, document);
426: else if ("org.netbeans.microedition.svg.SVGMenu".equals(typeID)) // NOI18N
427: ConverterSVG.convertMenu(id2item, item, document);
428: else if ("GROUP-org.netbeans.modules.vmd.components.svg.SvgMenuElementDC"
429: .equals(typeID)) // NOI18N
430: ConverterSVG.convertMenuElement(id2item, item, document);
431: else if ("org.netbeans.microedition.svg.SVGSplashScreen"
432: .equals(typeID)) // NOI18N
433: ConverterSVG.convertSplashScreen(id2item, item, document);
434: else if ("org.netbeans.microedition.svg.SVGWaitScreen"
435: .equals(typeID)) // NOI18N
436: ConverterSVG.convertWaitScreen(id2item, item, document);
437:
438: else if ("$MobileDevice".equals(id)) { // NOI18N
439: DesignComponent pointsCategory = MidpDocumentSupport
440: .getCategoryComponent(document,
441: PointsCategoryCD.TYPEID);
442: List<DesignComponent> list = DocumentSupport
443: .gatherSubComponentsOfType(pointsCategory,
444: MobileDeviceCD.TYPEID);
445: DesignComponent mobileDevice = list.get(0);
446: convertObject(item, mobileDevice);
447: } else if ("$StartPoint".equals(id)) { // NOI18N
448: DesignComponent pointsCategory = MidpDocumentSupport
449: .getCategoryComponent(document,
450: PointsCategoryCD.TYPEID);
451: List<DesignComponent> list = DocumentSupport
452: .gatherSubComponentsOfType(pointsCategory,
453: MobileDeviceCD.TYPEID);
454: DesignComponent mobileDevice = list.get(0);
455: DesignComponent startEventSource = mobileDevice
456: .readProperty(MobileDeviceCD.PROP_START)
457: .getComponent();
458: convertObject(item, startEventSource);
459: ConverterActions.convertCommandActionHandler(id2item, item,
460: startEventSource);
461: }
462:
463: else if (ConverterCustom.isClassComponent(item)) {
464: ConverterCustom.convertCustom(id2item, item, document);
465: }
466: }
467:
468: static ConverterItem convertConverterItem(
469: HashMap<String, ConverterItem> id2item, String value,
470: DesignDocument document) {
471: ConverterItem item = id2item.get(value);
472: if (item != null) {
473: convert(id2item, item, document);
474: if (item.isUsed())
475: return item;
476: }
477: return null;
478: }
479:
480: static DesignComponent convertConverterItemComponent(
481: HashMap<String, ConverterItem> id2item,
482: String propertyValue, DesignDocument document) {
483: ConverterItem item = convertConverterItem(id2item,
484: propertyValue, document);
485: return item != null ? item.getRelatedComponent() : null;
486: }
487:
488: // Created: NO, Adds: NO
489: static void convertObject(ConverterItem item,
490: DesignComponent component) {
491: item.setUsed(component);
492: }
493:
494: // Created: NO, Adds: NO
495: static void convertClass(ConverterItem item,
496: DesignComponent component) {
497: convertObject(item, component);
498: item.setClass();
499: component.writeProperty(ClassCD.PROP_INSTANCE_NAME, MidpTypes
500: .createStringValue(item.getID()));
501: Boolean lazy = getBoolean(item
502: .getPropertyValue("lazyInitialized")); // NOI18N
503: component.writeProperty(ClassCD.PROP_LAZY_INIT, MidpTypes
504: .createBooleanValue(lazy == null || lazy));
505: }
506:
507: }
|