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-2007 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:
042: package org.netbeans.modules.uml.reporting.dataobjects;
043:
044: import java.io.File;
045: import java.io.FileOutputStream;
046: import java.io.IOException;
047: import java.io.OutputStreamWriter;
048: import java.util.Arrays;
049: import java.util.logging.Level;
050: import java.util.logging.Logger;
051: import org.netbeans.modules.uml.core.metamodel.core.foundation.IPackage;
052: import org.netbeans.modules.uml.core.metamodel.diagrams.IDiagram;
053: import org.netbeans.modules.uml.core.metamodel.diagrams.IEdgeMapLocation;
054: import org.netbeans.modules.uml.core.metamodel.diagrams.IGraphicExportDetails;
055: import org.netbeans.modules.uml.core.metamodel.diagrams.IGraphicMapLocation;
056: import org.netbeans.modules.uml.core.metamodel.diagrams.ILabelMapLocation;
057: import org.netbeans.modules.uml.core.metamodel.diagrams.INodeMapLocation;
058: import org.netbeans.modules.uml.core.metamodel.diagrams.IProxyDiagram;
059: import org.netbeans.modules.uml.core.support.umlsupport.IETPoint;
060: import org.netbeans.modules.uml.core.support.umlsupport.IETRect;
061: import org.netbeans.modules.uml.core.support.umlsupport.StringUtilities;
062: import org.netbeans.modules.uml.core.support.umlutils.ETList;
063: import org.netbeans.modules.uml.reporting.ReportTask;
064: import org.netbeans.modules.uml.ui.controls.drawingarea.UIDiagram;
065: import org.netbeans.modules.uml.ui.support.projecttreesupport.ITreeDiagram;
066: import org.netbeans.modules.uml.ui.swing.drawingarea.SaveAsGraphicKind;
067: import org.openide.util.NbBundle;
068:
069: /**
070: *
071: * @author Sheryl
072: */
073: public class DiagramData extends ElementDataObject {
074: private IProxyDiagram pProxyDiagram;
075: private String dir;
076: private static int VIEWPORT_WIDTH = 1000;
077: private static int VIEWPORT_HEIGHT = 700;
078: private static int ZOOM_WIDTH = 120;
079: private static String FIT_TO_WINDOW_DIAGRAM_FILE_SUFFIX = "_fit.html"; // NOI18N
080: private int fitToScaleIndex = 0;
081: private int full_size_index = 0;
082:
083: /** Creates a new instance of DiagramData */
084: public DiagramData() {
085: }
086:
087: public DiagramData(ITreeDiagram diagram) {
088: this .pProxyDiagram = diagram.getDiagram();
089: setElement(diagram.getData().getDiagram().getDiagram());
090: }
091:
092: public IDiagram getDiagram() {
093: return pProxyDiagram.getDiagram();
094: }
095:
096: private double getFitToWindowScale(IDiagram diagram) {
097: if (diagram instanceof UIDiagram) {
098: double width = ((UIDiagram) diagram).getFrameWidth();
099: double height = ((UIDiagram) diagram).getFrameHeight();
100: double scale1 = VIEWPORT_WIDTH / width;
101: double scale2 = VIEWPORT_HEIGHT / height;
102: return scale1 > scale2 ? scale2 : scale1;
103: }
104: return 1;
105: }
106:
107: private void createFullDiagramFile(IDiagram pDiagram,
108: IGraphicExportDetails pDetails) {
109: if (pDiagram != null && pDetails != null) {
110: // get the jpg file for the diagram
111: String fullname = pDiagram.getFilename();
112: String name = StringUtilities.getFileName(fullname);
113: String jpg = name;
114: jpg += "_" + full_size_index + ReportTask.IMAGE_EXT;
115: // will place the name and documentation for the diagram at the top of the html
116: String diagName = pDiagram.getName();
117: String doc = pDiagram.getDocumentation();
118: String filename = getDirectoryPath() + File.separator
119: + name + ReportTask.HTML_EXT;
120:
121: StringBuilder page = new StringBuilder();
122: String str;
123:
124: page.append(getHTMLHeader());
125: page.append(getNavBar());
126:
127: if (diagName != null && diagName.length() > 0) {
128: page.append("<HR><H2>" + pDiagram.getDiagramKind2()
129: + " " + diagName + "</H2>"); // NOI18N
130: page.append("<P>" + doc + "</P>\r\n"); // NOI18N
131:
132: page
133: .append("<P ALIGN=\"CENTER\"><A HREF=\""
134: + name
135: + FIT_TO_WINDOW_DIAGRAM_FILE_SUFFIX
136: + // NOI18N
137: "\"><IMG SRC=\""
138: + // NOI18N
139: ReportTask
140: .getPathToReportRoot(pDiagram) + // NOI18N
141: "images/fit-to-window.png\" BORDER=n></A> </P>"); // NOI18N
142:
143: page.append("<HR>\r\n"); // NOI18N
144: }
145:
146: IETRect pMainRect = pDetails.getGraphicBoundingRect();
147: if (pMainRect != null) {
148: int nMainRectLeft = pMainRect.getLeft();
149: int nMainRectBottom = pMainRect.getTop(); // The y axis is opposite of the TS coordinates
150: int nMainRectTop = pMainRect.getBottom();
151: int nMainRectRight = pMainRect.getRight();
152:
153: str = "<IMG SRC=\"" + jpg
154: + "\" USEMAP=\"#MAP0-0\" BORDER=0 COORDS=\""
155: + // NOI18N
156: nMainRectLeft + nMainRectTop + nMainRectRight
157: + nMainRectBottom + "\">"; // NOI18N
158:
159: page.append(str);
160: page.append("<MAP NAME=\"MAP0-0\">"); // NOI18N
161:
162: // Process each item in the graphic
163: if (pDetails != null) {
164: // the information about the graphic is stored
165: // in these map locations
166: ETList<IGraphicMapLocation> pLocations = pDetails
167: .getMapLocations();
168: if (pLocations != null) {
169: // loop through the map locations
170: int count = pLocations.size();
171: for (int x = 0; x < count; x++) {
172: // the map location can either be a node, a label, or
173: // an edge
174: // need to process all of the nodes and labels first
175: // because the links go from center to center and in
176: // order to get the map right in the jpg those need
177: // to be listed after the nodes, because first entry
178: // in wins
179: IGraphicMapLocation pGMLoc = pLocations
180: .get(x);
181: if (pGMLoc != null) {
182: // see if we have a node or a label
183: if (pGMLoc instanceof INodeMapLocation) {
184: INodeMapLocation pLoc = (INodeMapLocation) pGMLoc;
185: // create the line in the jpg map for this node
186: String str2 = createLineForNode(
187: pDiagram, nMainRectBottom,
188: pLoc);
189: page.append(str2);
190: } else if (pGMLoc instanceof ILabelMapLocation) {
191: ILabelMapLocation pLabel = (ILabelMapLocation) pGMLoc;
192: // create the line in the jpg map for this label
193: String str2 = createLineForLabel(
194: nMainRectBottom, pLabel);
195: page.append(str2);
196: }
197: }
198: }
199: // we have processed all of the nodes and labels, now loop through
200: // the map locations again and do the links (edges)
201: for (int x = 0; x < count; x++) {
202: IGraphicMapLocation pGMLoc = pLocations
203: .get(x);
204: if (pGMLoc != null) {
205: // is it an edge
206: if (pGMLoc instanceof IEdgeMapLocation) {
207: IEdgeMapLocation pEdgeLoc = (IEdgeMapLocation) pGMLoc;
208: // create the line in the jpg map for the link
209: String str2 = createLineForLink(
210: nMainRectBottom, pEdgeLoc);
211: page.append(str2);
212: }
213: }
214: }
215: }
216: }
217: }
218:
219: page.append("<HR>\r\n"); // NOI18N
220: page.append(getNavBar());
221: page.append("</BODY>\r\n"); // NOI18N
222: page.append("</HTML>"); // NOI18N
223:
224: makePage(filename, page.toString());
225: }
226: }
227:
228: /**
229: * Format a string representing the node's points so that the jpg can include
230: * a map to go to a hyperlink when flying over the node in the jpg
231: *
232: *
233: * @param nMainRectBottom[in] The long value for the bottom of the jpg map
234: * @param pLoc[in] The object representing the information for the jpg
235: *
236: * @return CComBSTR The string representing the HTML
237: *
238: */
239: private String createLineForNode(IDiagram diagram,
240: int nMainRectBottom, INodeMapLocation pLoc) {
241: String str = "";
242: if (nMainRectBottom > 0 && pLoc != null) {
243: // Get the basic graphic map information
244: String name = pLoc.getName();
245:
246: // Get the node specific stuff
247: IETRect pRect = pLoc.getLocation();
248: if (pRect != null) {
249: int nRectLeft = pRect.getLeft();
250: int nRectTop = pRect.getTop(); // Y coordinates are flipped
251: int nRectBottom = pRect.getBottom();
252: int nRectRight = pRect.getRight();
253: long nTempRectLeft = nRectLeft;
254: long nTempRectTop = nRectTop;
255: long nTempRectRight = nRectRight;
256: long nTempRectBottom = nRectBottom;
257:
258: if (displayLink(pLoc.getElement())) {
259: // COORDS= "x1,y1,x2,y2" Where x1,y1 are the coordinates of the
260: // upper-left corner of the rectangle and x2,y2 are the coordinates
261: // of the lower-right coordinates of the rectangle.
262: str = "<AREA SHAPE=\"RECT\" COORDS=\""
263: + nTempRectLeft
264: + ", "
265: + // NOI18N
266: nTempRectTop + ", " + nTempRectRight
267: + ", "
268: + nTempRectBottom
269: + // NOI18N
270: "\" HREF=\""
271: + ReportTask.getPathToReportRoot(diagram)
272: + // NOI18N
273: ReportTask.getLinkTo(pLoc.getElement())
274: + "\" ALT=\"" + name + "\">"; // NOI18N
275: }
276: }
277: }
278: return str;
279: }
280:
281: /**
282: * Format a string representing the label's points so that the jpg can include
283: * a map to go to a hyperlink when flying over the label in the jpg
284: *
285: *
286: * @param nMainRectBottom[in] The long value for the bottom of the jpg map
287: * @param pLoc[in] The object representing the information for the jpg
288: *
289: * @return CComBSTR The string representing the HTML
290: *
291: */
292: private String createLineForLabel(int nMainRectBottom,
293: ILabelMapLocation pLoc) {
294: String str = "";
295: if (nMainRectBottom > 0 && pLoc != null) {
296: // Get the basic graphic map information
297: String name = pLoc.getName();
298:
299: // Get the node specific stuff
300: IETRect pRect = pLoc.getLocation();
301: if (pRect != null) {
302: int nRectLeft = pRect.getLeft();
303: int nRectTop = pRect.getTop(); // Y coordinates are flipped
304: int nRectBottom = pRect.getBottom();
305: int nRectRight = pRect.getRight();
306:
307: long nTempRectLeft = nRectLeft;
308: long nTempRectTop = nRectTop;
309: long nTempRectRight = nRectRight;
310: long nTempRectBottom = nRectBottom;
311:
312: if (displayLink(pLoc.getElement())) {
313: // COORDS= "x1,y1,x2,y2" Where x1,y1 are the coordinates of the
314: // upper-left corner of the rectangle and x2,y2 are the coordinates
315: // of the lower-right coordinates of the rectangle.
316: str = "<AREA SHAPE=\"RECT\" COORDS=\""
317: + nTempRectLeft
318: + ", "
319: + // NOI18N
320: nTempRectTop
321: + ", "
322: + nTempRectRight
323: + ", "
324: + nTempRectBottom
325: + // NOI18N
326: "\" HREF=\""
327: + ReportTask
328: .getPathToReportRoot(getDiagram())
329: + // NOI18N
330: ReportTask.getLinkTo(pLoc.getElement())
331: + "\" ALT=\"" + name + "\">"; // NOI18N
332: }
333: }
334: }
335: return str;
336: }
337:
338: /**
339: * Format a string representing the link's points so that the jpg can include
340: * a map to go to a hyperlink when flying over the link in the jpg
341: *
342: *
343: * @param nMainRectBottom[in] The long value for the bottom of the jpg map
344: * @param pLoc[in] The object representing the information for the jpg
345: *
346: * @return CComBSTR The string representing the HTML
347: *
348: */
349: private String createLineForLink(int nMainRectBottom,
350: IEdgeMapLocation pEdgeLoc) {
351: String str = ""; // NOI18N
352: if (nMainRectBottom > 0 && pEdgeLoc != null) {
353: // Get the basic graphic map information
354: String name = pEdgeLoc.getName();
355:
356: if (displayLink(pEdgeLoc.getElement())) {
357: // Get the node specific stuff
358: ETList<IETPoint> pPointsList = pEdgeLoc.getPoints();
359: if (pPointsList != null && pPointsList.size() > 0) {
360: str = "<AREA SHAPE=\"POLY\" COORDS=\""; // NOI18N
361: int ptCount = pPointsList.size();
362:
363: for (int i = 0; i < ptCount; i++) {
364: IETPoint pPoint = pPointsList.item(i);
365: Integer x = new Integer(pPoint.getX());
366: Integer y = new Integer(pPoint.getY());
367: str += x.toString() + ","; // NOI18N
368: str += y.toString();
369:
370: if (i + 1 != ptCount)
371: str += ","; // NOI18N
372: }
373: str += "\" HREF=\""
374: + ReportTask
375: .getPathToReportRoot(getDiagram())
376: + // NOI18N
377: ReportTask.getLinkTo(pEdgeLoc.getElement())
378: + "\" ALT=\"" + name + "\">"; // NOI18N
379:
380: }
381: }
382: }
383: return str;
384: }
385:
386: private boolean makePage(String fileName, String content) {
387: boolean result = false;
388: File f = new File(fileName);
389: try {
390: FileOutputStream fo = new FileOutputStream(f);
391: OutputStreamWriter writer = new OutputStreamWriter(fo,
392: ENCODING);
393: writer.write(content);
394: writer.flush();
395: writer.close();
396: result = true;
397: } catch (IOException e) {
398: Logger.getLogger(ElementDataObject.class.getName()).log(
399: Level.SEVERE,
400: getDiagram().getDiagramKind2() + " - "
401: + getDiagram().getName(), e);
402: }
403: return result;
404: }
405:
406: private String getDirectoryPath() {
407: return dir;
408: }
409:
410: private boolean createFilesForDiagram(IDiagram pDiagram,
411: IGraphicExportDetails pDetails, String imageString) {
412: if (pDiagram == null || pDetails == null)
413: return false;
414:
415: createFullDiagramFile(pDiagram, pDetails);
416:
417: // get the jpg file for the diagram
418: String fullname = pDiagram.getFilename();
419: String name = StringUtilities.getFileName(fullname);
420:
421: // will place the name and documentation for the diagram at the top of the html
422: String diagName = pDiagram.getName();
423: String filename = getDirectoryPath();
424: filename = filename + File.separator + name
425: + FIT_TO_WINDOW_DIAGRAM_FILE_SUFFIX;
426:
427: StringBuilder page = new StringBuilder();
428: page.append("<HTML>\n"); // NOI18N
429: page.append(" <HEAD>\n"); // NOI18N
430:
431: page
432: .append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset="
433: + // NOI18N
434: // System.getProperty("file.encoding") + "\">\n"); // NOI18N
435: ENCODING + "\">\n"); // NOI18N
436:
437: String str = "<TITLE>" + diagName + "</TITLE>\n"; // NOI18N
438: page.append(str + "\n"); // NOI18N
439: String scriptPath = getJavaScriptPath(pDiagram);
440: String script = getScript(scriptPath, name, imageString);
441: page.append(script + "\n"); // NOI18N
442: page.append(" </HEAD>\n"); // NOI18N
443: String body = getBody(scriptPath, diagName, name
444: + ReportTask.HTML_EXT);
445: page.append(body + "\n"); // NOI18N
446: page.append("</HTML>"); // NOI18N
447:
448: return makePage(filename, page.toString());
449: }
450:
451: private String getJavaScriptPath(IDiagram diagram) {
452: String path = ".."; // NOI18N
453: IPackage pkg = diagram.getOwningPackage();
454: assert pkg != null : "invalid package for diagram "
455: + diagram.getName(); // NOI18N
456: while (!pkg.equals(pkg.getProject())) {
457: path = path + "/.."; // NOI18N
458: pkg = pkg.getOwningPackage();
459: }
460: return path;
461: }
462:
463: private String getScript(String javascriptPath, String diagramName,
464: String imageString) {
465: String script = "";
466:
467: StringBuilder buffer = ReportTask
468: .readTemplate("org/netbeans/modules/uml/reporting/templates/script_template.html"); // NOI18N
469: script = buffer.toString();
470: script = script.replace("VIEWPORT_WIDTH", String
471: .valueOf(VIEWPORT_WIDTH)); // NOI18N
472: script = script.replace("VIEWPORT_HEIGHT", String
473: .valueOf(VIEWPORT_HEIGHT)); // NOI18N
474: script = script.replace("ZOOM_WIDTH", String
475: .valueOf(ZOOM_WIDTH)); // NOI18N
476: script = script.replace("LEFT_POSITION", String
477: .valueOf((VIEWPORT_WIDTH - ZOOM_WIDTH) / 2)); // NOI18N
478: script = script.replaceAll("DIAGRAM_IMAGE", diagramName); // NOI18N
479: script = script.replaceAll("SCRIPT_PATH", javascriptPath); // NOI18N
480: script = script.replaceAll("IMAGESTRING", imageString); // NOI18N
481: script = script.replaceAll("FIT_SCALE_INDEX", String
482: .valueOf(fitToScaleIndex)); // NOI18N
483: return script;
484: }
485:
486: private String getBody(String scriptPath, String diagramName,
487: String fileName) {
488: String body = "";
489: StringBuilder buffer = ReportTask
490: .readTemplate("org/netbeans/modules/uml/reporting/templates/body_template.html"); // NOI18N
491: body = buffer.toString();
492: body = body.replaceAll("SCRIPT_PATH", scriptPath); // NOI18N
493: body = body.replaceAll("%DIAGRAM_NAME%", getDiagram()
494: .getDiagramKind2()
495: + " " + diagramName); // NOI18N
496:
497: body = body.replaceAll("%DIAGRAM_DOC%", getDiagram()
498: .getDocumentation()); // NOI18N
499:
500: body = body.replaceAll("FULL_DIAGRAM_HTML", fileName); // NOI18N
501: body = body.replace("%BRAND%", NbBundle.getMessage(
502: DiagramData.class, "brand")); // NOI18N
503: body = body.replaceAll("%OVERVIEW%", // NOI18N
504: NbBundle.getMessage(ElementDataObject.class,
505: "Header_Overview")); // NOI18N
506: body = body.replaceAll("%PACKAGE%", // NOI18N
507: NbBundle.getMessage(ElementDataObject.class,
508: "Header_Package")); // NOI18N
509: body = body.replaceAll("%ELEMENT%", // NOI18N
510: NbBundle.getMessage(ElementDataObject.class,
511: "Header_Element")); // NOI18N
512: body = body.replaceAll("%DIAGRAM%", // NOI18N
513: NbBundle.getMessage(ElementDataObject.class,
514: "Header_Diagram")); // NOI18N
515: body = body.replaceAll("%HELP%", // NOI18N
516: NbBundle.getMessage(ElementDataObject.class,
517: "Header_Help")); // NOI18N
518: return body;
519: }
520:
521: public boolean toReport(File file) {
522: this .dir = file.getAbsolutePath();
523:
524: // get the IDiagram from the ProxyDiagram (NULL if the diagram is closed)
525: if (pProxyDiagram != null) {
526: IDiagram pDiagram = pProxyDiagram.getDiagram();
527:
528: if (pDiagram == null) {
529: pDiagram = ReportTask.loadDiagram(pProxyDiagram
530: .getFilename());
531: }
532:
533: if (pDiagram != null) {
534: // the diagram is open, so create its jpeg file
535: // first get the file that we are going to create
536:
537: String filename = pDiagram.getFilename();
538: String name = StringUtilities.getFileName(filename);
539:
540: double fitScale = getFitToWindowScale(pDiagram);
541:
542: double currentZoom = pDiagram.getCurrentZoom();
543: currentZoom = currentZoom > 1 ? 1 : currentZoom;
544: double[] scales = { 0.5 * currentZoom, currentZoom,
545: fitScale };
546: Arrays.sort(scales);
547: for (int i = 0; i < scales.length; i++) {
548: if (scales[i] == fitScale)
549: fitToScaleIndex = i;
550: else if (scales[i] == currentZoom)
551: full_size_index = i;
552: }
553:
554: StringBuilder imageString = new StringBuilder();
555: IGraphicExportDetails details = null; // the image to be used for full diagram page
556:
557: for (int i = 0; i < scales.length; i++) {
558: String imageName = getDirectoryPath()
559: + File.separator + name + "_" + i
560: + ReportTask.IMAGE_EXT;
561:
562: IGraphicExportDetails pDetails = pDiagram
563: .saveAsGraphic2(imageName,
564: SaveAsGraphicKind.SAFK_PNG,
565: scales[i]);
566: if (pDetails != null) {
567: int width = (int) (pDetails
568: .getFrameBoundingRect().getWidth() * scales[i]);
569: int height = (int) (pDetails
570: .getFrameBoundingRect().getHeight() * scales[i]);
571: imageString
572: .append(" { 'path' : '"
573: + name + "_" + i
574: + ReportTask.IMAGE_EXT
575: + "' , 'width' : " + width
576: + " , 'height' : " + height
577: + " }, "); // NOI18N
578: imageString.append("\n"); // NOI18N
579: if (i == full_size_index) {
580: details = pDetails;
581: }
582: }
583: }
584:
585: return createFilesForDiagram(pDiagram, details,
586: imageString.toString());
587: }
588: }
589: return false;
590: }
591: }
|