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.xml.schema.refactoring.ui;
043:
044: import java.awt.Color;
045: import java.awt.Image;
046: import java.util.ArrayList;
047: import java.util.Collections;
048: import java.util.Iterator;
049: import java.util.List;
050: import java.util.regex.Matcher;
051: import java.util.regex.Pattern;
052: import javax.swing.text.StyledDocument;
053: import org.netbeans.api.project.FileOwnerQuery;
054: import org.netbeans.api.project.Project;
055: import org.netbeans.api.project.ProjectUtils;
056: import org.netbeans.api.project.SourceGroup;
057: import org.netbeans.modules.xml.nbprefuse.AnalysisConstants;
058: import org.netbeans.modules.xml.schema.model.Schema;
059: import org.netbeans.modules.xml.schema.model.SchemaComponent;
060: import org.netbeans.modules.xml.schema.model.SchemaModel;
061: import org.netbeans.modules.xml.schema.model.visitor.FindUsageVisitor;
062: import org.netbeans.modules.xml.schema.model.visitor.Preview;
063: import org.netbeans.modules.xml.xam.Component;
064: import org.netbeans.modules.xml.xam.Model;
065: import org.netbeans.modules.xml.xam.NamedReferenceable;
066: import org.openide.ErrorManager;
067: import org.openide.filesystems.FileObject;
068: import org.openide.filesystems.Repository;
069: import org.openide.loaders.DataObject;
070: import org.openide.loaders.DataObjectNotFoundException;
071: import org.openide.nodes.AbstractNode;
072: import org.openide.nodes.Children;
073: import org.openide.text.CloneableEditorSupport;
074: import org.openide.text.Line;
075: import org.openide.text.NbDocument;
076: import org.openide.util.NbBundle;
077: import prefuse.data.Edge;
078: import prefuse.data.Graph;
079: import prefuse.data.Node;
080: import prefuse.util.ColorLib;
081:
082: /**
083: *
084: * @author Jeri Lockhart
085: */
086: public abstract class QueryUtilities {
087:
088: /**
089: * Get all the files in the project for the SchemaModel
090: * @param model The SchemaModel that is contained in the project
091: * @param sourceGroup The source group, such as JavaProjectConstants.SOURCES_TYPE_JAVA
092: * or Sources.TYPE_GENERIC
093: * @return a List of SourceGroups
094: *
095: */
096:
097: public static List<SourceGroup> getProjectSourceGroups(
098: final SchemaModel model, final String sourceGroupName) {
099: if (model == null || sourceGroupName == null) {
100: return null;
101: }
102: List<SourceGroup> result = new ArrayList<SourceGroup>();
103: Project proj = getProject(model);
104: //fix for issue 128660
105: if (proj == null)
106: return null;
107:
108: List<String> sourceGroupTypeList = new ArrayList<String>();
109: sourceGroupTypeList.add(sourceGroupName);
110:
111: for (String type : sourceGroupTypeList) {
112: SourceGroup[] srcGrps = ProjectUtils.getSources(proj)
113: .getSourceGroups(type);
114: if (srcGrps != null) {
115: for (SourceGroup srcGrp : srcGrps) {
116: result.add(srcGrp);
117: }
118: }
119: }
120: return result;
121: }
122:
123: /**
124: *
125: *
126: */
127: private static Project getProject(final Model model) {
128: if (model == null) {
129: return null;
130: }
131: FileObject fileObj = (FileObject) model.getModelSource()
132: .getLookup().lookup(FileObject.class);
133: return FileOwnerQuery.getOwner(fileObj);
134:
135: }
136:
137: /**
138: * Use FindUsageVisitor to get the usages Preview for a Named
139: *
140: */
141:
142: @SuppressWarnings("unchecked")
143: public static Preview getUsagesPreview(Schema schema,
144: NamedReferenceable ref) {
145: FindUsageVisitor usage = new FindUsageVisitor();
146: return usage.findUsages(Collections.singletonList(schema), ref);
147:
148: }
149:
150: /**
151: * Creates an AbstractNode with the given label
152: * with Children.SortedArray and a String comparator
153: * Used by Analysis modules to create category container
154: * nodes for Global Complex Types, Global Elements, etc
155: *
156: *
157: */
158: public static AbstractNode createCategoryNode(
159: AnalysisConstants.GlobalTypes type) {
160: Children.SortedArray children = new Children.SortedArray();
161: children.setComparator(new NodeComparator());
162: AbstractNode catNode = new AbstractNode(children) {
163: org.openide.nodes.Node node = null;
164:
165: private org.openide.nodes.Node getDelegateNode() {
166: if (node == null) {
167: try {
168: node = DataObject.find(
169: Repository.getDefault()
170: .getDefaultFileSystem()
171: .getRoot()).getNodeDelegate();
172: } catch (DataObjectNotFoundException ex) {
173: }
174: }
175: return node;
176: };
177:
178: public Image getIcon(int type) {
179: org.openide.nodes.Node n = getDelegateNode();
180: return n != null ? n.getIcon(type) : super
181: .getIcon(type);
182: }
183:
184: public Image getOpenedIcon(int type) {
185: org.openide.nodes.Node n = getDelegateNode();
186: return n != null ? n.getOpenedIcon(type) : super
187: .getOpenedIcon(type);
188: }
189: };
190: String label = null;
191: switch (type) {
192: case COMPLEX_TYPE:
193: label = NbBundle.getMessage(QueryUtilities.class,
194: "LBL_GlobalComplexTypes");
195: break;
196: case SIMPLE_TYPE:
197: label = NbBundle.getMessage(QueryUtilities.class,
198: "LBL_GlobalSimpleTypes");
199: break;
200: case PRIMITIVE:
201: label = NbBundle.getMessage(QueryUtilities.class,
202: "LBL_Primitives");
203: break;
204: case ELEMENT:
205: label = NbBundle.getMessage(QueryUtilities.class,
206: "LBL_GlobalElements");
207: break;
208: case GROUP:
209: label = NbBundle.getMessage(QueryUtilities.class,
210: "LBL_GlobalGroups");
211: break;
212: case ATTRIBUTE:
213: label = NbBundle.getMessage(QueryUtilities.class,
214: "LBL_GlobalAttributes");
215: break;
216: case ATTRIBUTE_GROUP:
217: label = NbBundle.getMessage(QueryUtilities.class,
218: "LBL_GlobalAttributeGroups");
219: break;
220: case BASE_COMPLEX_TYPES:
221: label = NbBundle.getMessage(QueryUtilities.class,
222: "LBL_Global_ComplexTypes_With_Derivations");
223: break;
224: }
225:
226: catNode.setName(label);
227: return catNode;
228: }
229:
230: /**
231: * Returns a color palette of given size that cycles through
232: * the hues of the HSB (Hue/Saturation/Brightness) color space.
233: * @param size the size of the color palette
234: * @param s the saturation value to use
235: * @param b the brightness value to use
236: * @param huesToExclude null or an array of hues to exclude from palette
237: * @return the color palette
238: */
239: public static int[] getHSBPalette(int size, float s, float b,
240: AnalysisConstants.HSBHues[] huesToExclude) {
241: int[] cm = new int[size];
242: int igen = 0;
243: for (int i = 0; i < size; i++) {
244: float h = 0;
245: boolean goodHue = false;
246: while (goodHue == false) {
247: h = ((float) igen++) / (size);
248: if (huesToExclude != null) {
249: for (AnalysisConstants.HSBHues exH : huesToExclude) {
250: goodHue = !isInColorFamily(h, exH);
251: if (goodHue == false) {
252: break;
253: }
254: }
255: } else {
256: goodHue = true;
257: }
258: }
259: cm[i] = ColorLib.hsb(h, s, b);
260: }
261: return cm;
262: }
263:
264: private static boolean isInColorFamily(float h,
265: AnalysisConstants.HSBHues hue) {
266: if (hue == null) {
267: return false;
268: }
269: return (h >= hue.low() && h <= hue.high());
270:
271: }
272:
273: /**
274: * Print out of prefuse graph for debugging
275: *
276: *
277: */
278: public static void dumpGraph(Graph graph) {
279: // if (graph == null){
280: // return;
281: // }
282: //
283: // Iterator nodeIt = graph.nodes();
284: // Iterator edgeIt = graph.edges();
285: // System.out.println("NODES:");
286: // while (nodeIt.hasNext()){
287: // Node node = Node.class.cast(nodeIt.next());
288: // System.out.println(" ");
289: // System.out.println(node.toString());
290: // System.out.println("Node Attributes:");
291: // Map map = node.getAttributes();
292: // Set entries = map.entrySet();
293: // for (Iterator i = entries.iterator(); i.hasNext();){
294: // Entry entry = Entry.class.cast(i.next());
295: // System.out.println(entry.getKey() + ": " + entry.getValue());
296: // }
297: // Iterator nodeEdgesIt = node.edges();
298: // while(nodeEdgesIt.hasNext()){
299: // Edge edge = Edge.class.cast(nodeEdgesIt.next());
300: // System.out.println("First node: " + edge.getSourceNode().toString()
301: // + " Second node: " + edge.getTargetNode().toString()
302: // + " isDirected: " + edge.isDirected()
303: // );
304: // }
305: // }
306: // System.out.println("EDGES:");
307: // while (edgeIt.hasNext()){
308: // Edge edge = Edge.class.cast(edgeIt.next());
309: // System.out.println(" ");
310: // System.out.println(edge.toString());
311: // System.out.println("Edge Attributes:");
312: // Map map = edge.getAttributes();
313: // Set entries = map.entrySet();
314: // for (Iterator i = entries.iterator(); i.hasNext();){
315: // Entry entry = Entry.class.cast(i.next());
316: // System.out.println(entry.getKey() + ": " + entry.getValue());
317: // }
318: // System.out.println("First Node: " + edge.getSourceNode().toString());
319: // System.out.println("Second Node: " + edge.getTargetNode().toString());
320: // }
321: //
322: }
323:
324: /**
325: * @return a trimmed snippet of XML from the 1st line of the Schema Component
326: * @param sc a Schema Component
327: *
328: */
329: public static String getTextForSchemaComponent(final Component comp) {
330: SchemaComponent sc = null;
331: if (comp instanceof SchemaComponent) {
332: sc = SchemaComponent.class.cast(comp);
333: }
334: if (sc == null) {
335: return ""; //NOI18N
336: }
337: // TODO - if the line doesn't contain the target (query component name) string, keep searcing subsequent lines
338: DataObject dobj = null;
339: try {
340: dobj = DataObject.find((FileObject) sc.getModel()
341: .getModelSource().getLookup().lookup(
342: FileObject.class));
343: } catch (DataObjectNotFoundException ex) {
344: ErrorManager.getDefault().notify(ex);
345: }
346: CloneableEditorSupport editor = (CloneableEditorSupport) dobj
347: .getCookie(org.openide.cookies.EditorCookie.class);
348: Line.Set s = editor.getLineSet();
349: StyledDocument doc = editor.getDocument();
350:
351: int position = (int) sc.findPosition();
352: int line = NbDocument.findLineNumber(doc, position);
353: int col = NbDocument.findLineColumn(doc, position);
354: Line xmlLine = s.getCurrent(line);
355: String nodeLabel = xmlLine.getText().trim();
356: // substitute xml angle brackets <> for < and >
357: Pattern lt = Pattern.compile("<"); //NOI18N
358: Matcher mlt = lt.matcher(nodeLabel);
359: nodeLabel = mlt.replaceAll("<"); //NOI18N
360: Pattern gt = Pattern.compile(">"); //NOI18N
361: Matcher mgt = gt.matcher(nodeLabel);
362: nodeLabel = mgt.replaceAll(">"); //NOI18N
363: return boldenRefOrType(nodeLabel);
364: }
365:
366: // TODO get xml snippet for line that contains the
367: // query component name
368: /**
369: * If the label contains ref= or type=
370: * the substring containing the named portion of the attribute
371: * will be surrounded with html bold tags
372: * e.g.,
373: * input param <xsd:element ref="comment" minOccurs="0"/>
374: * return <xsd:element ref="<b>comment</b>" minOccurs="0"/>
375: *
376: *
377: */
378: private static String boldenRefOrType(String label) {
379: // find index of type or ref
380: // find 1st occurence of " from index
381: // find 1st occurence of : after ", if any
382: // insert <b>
383: // find closing "
384: // insert </b>
385: int it = label.indexOf(" type"); //NOI18N
386: if (it < 0) {
387: it = label.indexOf(" ref"); //NOI18N
388: }
389: if (it < 0) {
390: // no type or ref found
391: return label;
392: }
393: int iq1 = label.indexOf('"', it);
394: if (iq1 < it) {
395: // no begin quote
396: return label;
397: }
398: int ic = label.indexOf(':', iq1);
399: // if (ic < iq1){
400: // // no colon
401: // }
402: int iq2 = label.indexOf('"', iq1 + 1);
403: if (iq2 < iq1 || ic > iq2) {
404: // couldn't find closing quote for tag
405: return label;
406: }
407: int ib1 = -1;
408: if (ic > -1) {
409: ib1 = ic + 1;
410: } else {
411: ib1 = iq1 + 1;
412: }
413: StringBuffer l = new StringBuffer(label);
414: l.insert(ib1, "<b>");
415: // the close quote has now been pushed right 3 spaces
416: l.insert(iq2 + 3, "</b>");
417: return l.toString();
418:
419: }
420:
421: /**
422: * An array of ToolTipLine instances can be passed to
423: * GraphUtilities.createHTMLToolTip()
424: * ToolTipLine contains the text, the font size as a percentage of the default size,
425: * the horizontal alignment (center, left, or right), and the font color.
426: *
427: *
428: */
429: public static class ToolTipLine {
430: public enum HorizontalAlignment {
431: CENTER("center"), // NOI18N
432: LEFT("left"), // NOI18N
433: RIGHT("right"); // NOI18N
434:
435: private final String name;
436:
437: HorizontalAlignment(String name) {
438: this .name = name;
439: }
440:
441: public String toString() {
442: return name;
443: }
444: }
445:
446: private String text = ""; //NOI18N
447: private int fontSizePercentage = 100;
448: private int rgbColor = Color.BLACK.getRGB();
449: private HorizontalAlignment hAlign = HorizontalAlignment.CENTER;
450:
451: public ToolTipLine(String text, int fontSizePercentage,
452: int rgbColor, HorizontalAlignment hAlign) {
453:
454: this .text = text;
455: this .fontSizePercentage = fontSizePercentage;
456: this .rgbColor = rgbColor;
457: this .hAlign = hAlign;
458: }
459:
460: public ToolTipLine(String text, int rgbColor) {
461: this .text = text;
462: this .rgbColor = rgbColor;
463: }
464:
465: public ToolTipLine(String text) {
466: this .text = text;
467: }
468:
469: public String getHorizontalAlignmentAsString() {
470: return this .hAlign.toString();
471: }
472:
473: public String getText() {
474: return " " + this .text + " "; //NOI18N
475: }
476:
477: public String getFontSizePercentageAsString() {
478: return String.valueOf(fontSizePercentage);
479: }
480:
481: // example return value "(145,123,000)"
482: public String getColorAsRGBString() {
483: Color color = new Color(rgbColor);
484: StringBuffer str = new StringBuffer();
485: str.append("("); //NOI18N
486: str.append(String.valueOf(color.getRed()));
487: str.append(","); //NOI18N
488: str.append(String.valueOf(color.getGreen()));
489: str.append(","); //NOI18N
490: str.append(String.valueOf(color.getBlue()));
491: str.append(")"); //NOI18N
492: return str.toString();
493: }
494:
495: }
496: }
|