/* * CCVisu is a tool for visual graph clustering * and general force-directed graph layout. * This file is part of CCVisu. * * Copyright (C) 2005-2012 Dirk Beyer * * CCVisu is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * CCVisu is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with CCVisu; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Please find the GNU Lesser General Public License in file * license_lgpl.txt or http://www.gnu.org/licenses/lgpl.txt * * Dirk Beyer (firstname.lastname@uni-passau.de) * University of Passau, Bavaria, Germany */ package org.sosy_lab.ccvisu; import static org.sosy_lab.ccvisu.CCVisuController.endl; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; import javax.swing.JInternalFrame; import org.sosy_lab.ccvisu.graph.GraphData; import org.sosy_lab.ccvisu.measuring.calldep.DistanceVertexContainer; import org.sosy_lab.ccvisu.measuring.calldep.colors.ColorProvider; import org.sosy_lab.ccvisu.readers.filter.BlacklistPackageFilter; import org.sosy_lab.ccvisu.readers.filter.Filter; import org.sosy_lab.ccvisu.readers.filter.InternalRelations; import org.sosy_lab.ccvisu.readers.filter.Sort; import org.sosy_lab.ccvisu.readers.filter.Uniq; import org.sosy_lab.ccvisu.readers.filter.WhitelistRelationFilter; import org.sosy_lab.ccvisu.ui.interfaces.AbstractUI; import org.sosy_lab.ccvisu.ui.interfaces.FrameDisplayMouseAdapter; import org.sosy_lab.ccvisu.ui.interfaces.GraphLoadedListener; import org.sosy_lab.ccvisu.ui.interfaces.WriterDataGraphicsDISPListener; import org.sosy_lab.util.Colors; /** * Command-line options. */ public class Options { private static final String CCVISU_URL = "http://ccvisu.sosy-lab.org"; public static final String VERSION = "CCVisu 3.5, 2012-12-24"; // This enum construction is not yet used everywhere. public enum OptionsEnum { // General options without argument. help("h", "Boolean", "false", "display this help message and exit"), version("v", "Boolean", "false", "print version information and exit"), quiet("q", "Boolean", "false", "quiet mode"), warnings("w", "Boolean", "false", "enable warnings"), verbose("", "Boolean", "false", "verbose mode"), assertCheck("a", "Boolean", "false", "check if assertions are enabled"), guiMode("g", "Boolean", "false", "GUI mode (provides a window to set options)"), inputName("i", "String", "stdin", "read input data from given file <str>"), outputName("o", "String", "stdout", "write output data to given file <str>"), // Layouting options. dim("", "Integer", "2", "number of dimensions of the layout, up to 3"), iter("", "Integer", "100", "number of iterations of the minimizer;" + endl + Options.helpOptionNameIndent("") + "choose appropriate values by observing the convergence of energy"), energyDiffThreshold("", "Float", "0.0f", "layouting stop criterion: minimal threshold for energy difference between iterations" + endl + "set to 0.0f to disable this feature"), autoStopIterating("", "Boolean", "false", "Stop iterating if the percentage change of the energy is below a hardcoded threshold for the active repulsion strategy?"), initLayout("", "String", "", "use layout (LAY format) from file <str> as initial layout"), fixedInitPos("", "Boolean", "false", "fix positions for vertices from initial layout given by -initLayout"), // For CVS reader. timeWindow("", "Integer", "180000", "time window for change transaction recovery, in milli-seconds"), slidingTW("", "Boolean", "false", "use sliding time windows instead of fixed time window, i.e., the time window 'slides':" + endl + Options.helpOptionNameIndent("") + "a new commit node is created if the time difference between two commited files is bigger" + endl + Options.helpOptionNameIndent("") + "than the time window"), // For layout output. hideSource("", "Boolean", "false", "draw only vertices that are not source of an edge." + endl + Options.helpOptionNameIndent("") + "In co-change graphs, all change-transaction vertices" + endl + Options.helpOptionNameIndent("") + "are source vertices"), minVert("", "Float", "2.0f", "size of the smallest vertex disc; diameter"), fontSize("", "Integer", "14", "font size of vertex annotations"), // Draw a ring around the vertex discs (filled circles, strokes). blackCircle("", "Boolean", "true", ""), ringColor("", "String", "GRAY", "Color of the ring around the vertex discs"), depDegreeColor("", "Boolean", "false", "Color of the vertex disc determined by dep-degree"), enableFeatureVisu("", "Boolean", "false", "Enables support for features"), // Show the Edges showEdges("", "Boolean", "false", "show the edges of the graph; available only for CVS and RFS inFomat"), // Options for VRML writer. // Scale positions in the layout. scalePos("", "Float", "1.0f", "scaling factor for the layout to adjust; VRML and SVG only"), // Only for DISP writer. /** If true, the layout is already displayed while the minimizer is still improving it, and a simple mouse click on the canvas updates the current layout on the screen. If false, the layout is displayed only after minimization is completed. */ anim("", "Boolean", "true", ""), // Do not display the GUI window if the DISP writer is used disableDISPGuiControls("", "Boolean", "false", "don't display the GUI window for the DISP writer"), disableVertexDragging("", "Boolean", "false", "disable vertex dragging"), stretchGraphToBounds("", "Boolean", "false", "stretch visual graph representation so that it takes up whole display frame"), considerAuxVertices("", "Boolean", "false", "consider auxiliary vertices when calculating graphical layout representation"), showRefreshingLabel("", "Boolean", "true", "always inform the user that ccvisu is currently refreshing the screen"), enableToolTips("", "Boolean", "false", "enable tool tips for drawing canvas"), // For all writers. showAllLabels("", "Boolean", "false", "annotate each vertex with its name"), /** Heuristically shorten vertex labels. */ shortNames("", "Boolean", "false", "shorten vertex labels"), dispFilter("", "Boolean", "false", "show extra controls for display filter"), // Switch on user-defined marker to emphasize certain vertices. initGroups("", "String", "", "assign vertices to groups (and colors) according to file <str>" + endl + Options.helpOptionNameIndent("") + "(cf. file marker_script.example.txt as example)"), computeCut("", "Boolean", "false", "interpret group assignment by -initGroups as partition and compute the cut"), writeClusteringMeasures("", "String", "", "Calculate the measures of the given clustering (group file) and write it to the specified file."), clusters("", "Integer", "0", "(max) number of clusters to extract"), clusterMergeDistancePercent("", "Float", "0.03f", "Merge partitions within distance (percent of layout diagonal; e.g. 0.05)."), clusterMinDistancePercent("", "Float", "0.4f", "Do not merge a pair of clusters if the distance " + endl + Options.helpOptionNameIndent("") + "of their barycenters is larger than this value (percent of layout diagonal)."), // Dependency visualization cdep("", "Boolean", "false", "Calculate and visualize dependencies."), dependencyColoring("", "String", ColorProvider.getInstance().getDefaultColorOption(), "Set the coloring scheme used for dependency visualization."), dependencyShowLabels("", "Integer", "3", "Set the number of labels to automatically show when calculating dependencies"), dependencyAlgorithm("", "String", DistanceVertexContainer.ALGORITHM_NAME, "Set the algorithm for dependency calculations"), // Extract information from source code sourceDirectory("srcDir", "String", "", "Path to the source code. " + "This is required when extracting from sourcecode."), sourceLibraries("srcLibs", "String", "", "Path to the libraries"), sourceBlacklist("srcBlacklst", "String", "", "List of all packages to be " + "ignored when creating the relations. Strings must be separated by ';'"), sort("sort", "Boolean", "false", "Sort output relations."), uniq("uniq", "Boolean", "false", "Output every tuple at most once. This option sorts implicitly."), internal("internal", "Boolean", "false", "Use only internal relations."), openURL( "", "Boolean", "false", "the vertex names can be considered as URL and opened in a web browser." + endl + Options.helpOptionNameIndent("") + "This option used with DISP output requires to hold CTRL KEY while clicking"), browser("", "String", "", "browser <str> will be invoked; if empty, CCVisu will try to guess"); private final String altOptName; private final String type; private final String defaultValue; private final String description; OptionsEnum(String altOptName, String type, String defaultValue, String description) { this.altOptName = altOptName; this.type = type; this.defaultValue = defaultValue; this.description = description; } String getAltOptName() { return altOptName; } String getType() { return type; } public String getDefault() { return defaultValue; } public String getDescription() { return description; } } public class Option { private final String optName; private final String altOptName; private final String type; private final String defaultValue; private final String description; private Boolean valueBoolean; private Integer valueInteger; private Float valueFloat; private String valueString; Option(String optName, String altOptName, String type, String defaultValue, String description) { this.optName = optName; this.altOptName = altOptName; this.type = type; this.defaultValue = defaultValue; this.description = description; if (type.equals("Boolean")) { valueBoolean = new Boolean(defaultValue); } if (type.equals("Integer")) { valueInteger = new Integer(defaultValue); } if (type.equals("Float")) { valueFloat = new Float(defaultValue); } if (type.equals("String")) { valueString = new String(defaultValue); } } public String getOptName() { return optName; } public String getAltOptName() { return altOptName; } public String getType() { return type; } public String getDefault() { return defaultValue; } public String getDescription() { return description; } public boolean getBool() { assert (valueBoolean != null); return valueBoolean; } public void set(boolean value) { assert (valueBoolean != null); valueBoolean = new Boolean(value); } public int getInt() { assert (valueInteger != null); return valueInteger; } public void set(int value) { assert (valueInteger != null); valueInteger = new Integer(value); } public float getFloat() { assert (valueFloat != null); return valueFloat; } public void set(float pValue) { assert (valueFloat != null); valueFloat = new Float(pValue); } public String getString() { assert (valueString != null); return valueString; } public void set(String value) { assert (valueString != null); valueString = new String(value); } public String getValue() { String value = ""; if (type.equals("Boolean")) { value = valueBoolean.toString(); } if (type.equals("Integer")) { value = valueInteger.toString(); } if (type.equals("Float")) { value = valueFloat.toString(); } if (type.equals("String")) { value = "'" + valueString.toString() + "'"; } return value; } @Override public String toString() { return optName; } } private Map<OptionsEnum, Option> settings = new HashMap<OptionsEnum, Option>(); private Option getOption(String optionName) { for (Option o : settings.values()) { if (optionName.equalsIgnoreCase("-" + o.toString())) { return o; } if (optionName.equalsIgnoreCase("-" + o.altOptName)) { return o; } if (optionName.equalsIgnoreCase("--" + o.toString())) { return o; } if (optionName.equalsIgnoreCase("--" + o.altOptName)) { return o; } } return null; } public Option getOption(OptionsEnum option) { return settings.get(option); } /** Input formats. */ public enum InFormat { RSF("rsf", "Relational Standard Files", "Graph (relation) in Relational Standard Format (RSF).", true), LAY("lay", "Layout Files", "Graph layout in textual format.", true), CVS("log", "CVS Log Files", "CVS log format (produce with 'cvs log -Nb').", true), SVN("xml", "SVN Log Files in XML", "SVN log format (produce with 'svn log -v --xml').", true), SRC("src", "Java Source Code", "Use the java source of a software system as input.", false), DOX("xml", "Doxygen Output as XML Files", "Doxygen XML dump format (produce with 'doxygen').", true), ODS("ods", "Open Document Spreadsheet Files", "ODS Spreadsheet.", true), AUX("aux", "Auxiliary Graph Input", "Graph is passed as data structure from a third-party client.", false); private final String fileExtension; private final String shortDescription; private final String description; private final boolean defaultGuiLoad; /** * Constructor of a file format. * * @param fileExtension The ending of the file. * @param shortDescription Short description of the input file type. * @param description Long description of the input file type. * @param defaultGuiLoad <code>true</code> if the file format is to be shown as a * default load option in the GUI loader, <code>false</code> otherwise. */ InFormat(String fileExtension, String shortDescription, String description, boolean defaultGuiLoad) { this.fileExtension = fileExtension; this.shortDescription = shortDescription; this.description = description; this.defaultGuiLoad = defaultGuiLoad; } /** * @return the fileExtension */ public String getFileExtension() { return '.' + fileExtension; } /** * @return A short description of the input format. */ public String getShortDescription() { return shortDescription; } public String getDescription() { return description; } public boolean isDefaultGuiLoad() { return this.defaultGuiLoad; } } /** Output formats. */ public enum OutFormat { RSF("rsf", "Relational Standard Files", "Graph (relation) in Relational Standard Format (RSF)."), CRSF("rsf", "Relational Standard Files containing Clusters", "Graph clustering in Relational Standard Format (RSF)."), LAY("lay", "Layout Files", "Graph layout in textual format."), SVG("svg", "SVG Files", "Graph layout in SVG format."), VRML("wrl", "VRML Files", "Graph layout in VRML format."), GML("gml", "GraphML Files", "Graph in GraphML format."), GXL("gxl", "GXL Files", "Graph in GXL format."), DISP("disp", "Screen Output", "Display graph layout on screen."), STATS("stats", "Statistics Files", "Statistics in textual format."), CALLDEP("rsf", "Calldep output", "Output of the calldep algorithm."), DIST("dst", "Node-pair distances", "Euclidian-distances between all node-pairs of the graph."), NULL("null", "Null output", "Null output"); private final String fileExtension; private final String shortDescription; private final String description; OutFormat(String fileExtension, String shortDescription, String description) { this.fileExtension = fileExtension; this.shortDescription = shortDescription; this.description = description; } /** * @return the fileExtension */ public String getFileExtension() { return '.' + fileExtension; } /** * @return the formatName */ public String getShortDescription() { return shortDescription; } public String getDescription() { return description; } } /** Verbosity levels. */ public enum Verbosity { /** Don't say much, only report errors. */ QUIET(0), /** Print warnings as well. */ WARNING(1), /** Print light warnings as well. */ WARNINGLIGHT(2), /** Print statistics and other information. */ VERBOSE(3), /** Print debugging information as well. */ DEBUG(4); private int level; Verbosity(int level) { this.level = level; } public boolean isAtLeast(Verbosity verbosity) { return this.level >= verbosity.level; } } // Input format public InFormat inFormat = InFormat.RSF; // Output format. OutFormat outFormat = OutFormat.DISP; /** Filters that are applied to the given Relation. */ Collection<Filter> filters = new LinkedList<Filter>(); public GraphData initialLayout = null; public FrameDisplayMouseAdapter frameDisplayMouseAdapter = null; public WriterDataGraphicsDISPListener writerDataGraphicsDISPListener = null; public AbstractUI gui = null; // For energy model. /* Exponent of the Euclidian distance in the attraction * term of the energy (default: 1). */ public float attrExponent = 1.0f; // Exponent of the Euclidian distance in the repulsion term of the energy (default: 0). public float repuExponent = 0.0f; /* Use vertex repulsion instead of edge repulsion, * true for vertex repulsion, false for edge repulsion * (default: edge repulsion). */ public boolean vertRepu = false; /* Use unweighted model by ignoring the edge weights, * true for unweighted, false for weighted (default: weighted). */ public boolean noWeight = false; /* Gravitation factor for the Barnes-Hut-procedure, * attraction to the barycenter (default: 0.001). */ public float gravitation = 0.001f; /** Background color for layout output. */ public Colors backColor = Colors.WHITE; public JInternalFrame frame = null; /** In/Out parameter representing the graph. */ public final GraphData graph; public InformationCollector infoCollector; public Verbosity verbosity = Verbosity.WARNING; public Collection<GraphLoadedListener> graphLoadedListeners = new LinkedList<GraphLoadedListener>(); public Options(GraphData graph) { this.graph = graph; for (OptionsEnum o : OptionsEnum.values()) { settings.put(o, new Option(o.toString(), o.getAltOptName(), o.getType(), o.getDefault(), o.getDescription())); } } /** * Parses command-line options. * @param args Array of command-line options. */ public void parseCmdLine(String[] args) { List<String> argsList = Arrays.asList(args); if (argsList.size() == 0) { settings.get(OptionsEnum.guiMode).set(true); } Collection<String> whitelist = new LinkedList<String>(); for (ListIterator<String> it = argsList.listIterator(); it.hasNext();) { String arg = Options.getNext(it); // General options with argument. // Input format. if (arg.equalsIgnoreCase("-inFormat")) { arg = Options.getNext(it); inFormat = Options.getInFormat(arg); } // Output format. else if (arg.equalsIgnoreCase("-outFormat")) { arg = Options.getNext(it); outFormat = Options.getOutFormat(arg); } // Options for DOX reader. // Relations that should be used for computing layout. else if (arg.equalsIgnoreCase("-relSelect")) { arg = Options.getNext(it); whitelist.add(arg); } // Energy model. // Attraction exponent. else if (arg.equalsIgnoreCase("-attrExp")) { arg = Options.getNext(it); attrExponent = Float.parseFloat(arg); } // Repulsion exponent. else if (arg.equalsIgnoreCase("-repuExp")) { arg = Options.getNext(it); repuExponent = Float.parseFloat(arg); } // Node repulsion. else if (arg.equalsIgnoreCase("-vertRepu")) { vertRepu = true; } // No weights. else if (arg.equalsIgnoreCase("-noWeight")) { noWeight = true; } // Gravitation factor. else if (arg.equalsIgnoreCase("-grav")) { arg = Options.getNext(it); gravitation = Float.parseFloat(arg); } // TODO: Remove/convert to new the following: // Options for output writers. // Avoid black circles around the filled circles for vertices (strokes). else if (arg.equalsIgnoreCase("-noBlackCircle")) { settings.get(OptionsEnum.blackCircle).set(false); } // Background color. else if (arg.equalsIgnoreCase("-backcolor")) { arg = Options.getNext(it); backColor = Colors.valueOfUpper(arg); } // Only for display writer. // Animation of layout during minimization, if outFormat is DISP. else if (arg.equalsIgnoreCase("-noAnim")) { settings.get(OptionsEnum.anim).set(false); } // 'Automatic' option. else if (getOption(arg) != null) { Option option = getOption(arg); if (option.getType().equals("Boolean")) { option.set(true); } else if (option.getType().equals("Integer")) { arg = Options.getNext(it); option.set(Integer.parseInt(arg)); } else if (option.getType().equals("Float")) { arg = Options.getNext(it); option.set(Float.parseFloat(arg)); } else if (option.getType().equals("String")) { arg = Options.getNext(it); option.set(arg); } } // Unknown option. else { System.err.println("Usage error: Option '" + arg + "' unknown."); System.exit(1); } } // for parsing command-line // Set verbosity... if (getOption(OptionsEnum.quiet).getBool()) { verbosity = Verbosity.QUIET; } else if (getOption(OptionsEnum.warnings).getBool()) { verbosity = Verbosity.WARNING; } else if (getOption(OptionsEnum.verbose).getBool()) { verbosity = Verbosity.VERBOSE; } setFilters(whitelist); } private void setFilters(Collection<String> whitelist) { // the order of the following is relevant // as tuples will get rearranged, changed and rewritten if (getOption(OptionsEnum.internal).getBool()) { filters.add(new InternalRelations(verbosity)); } if (whitelist.size() > 0) { filters.add(new WhitelistRelationFilter(whitelist)); } if (getOption(OptionsEnum.sort).getBool() && !getOption(OptionsEnum.uniq).getBool()) { // uniq sorts implicitly filters.add(new Sort()); } if (getOption(OptionsEnum.uniq).getBool()) { filters.add(new Uniq()); } if (!getOption(OptionsEnum.sourceBlacklist).getString().isEmpty()) { Collection<String> blacklistedPackages = Arrays.asList(getOption(OptionsEnum.sourceBlacklist).getString().split(";")); filters.add(new BlacklistPackageFilter(blacklistedPackages)); } } /** * Checks whether the current command-line argument a parameter. * If there is no follower argument, it exits the program. * @param it String list iterator that points to the current argument. */ private static String getNext(ListIterator<String> it) { if (!it.hasNext()) { System.err.println("Usage error: Option '" + it.previous() + "' requires an argument (file)."); System.exit(1); } return it.next(); } /** * Returns a String with the version information. */ public String versionMessage() { StringBuilder versionText = new StringBuilder(); versionText.append(Options.VERSION + "." + endl); versionText.append("Copyright (C) 2005-2010 Dirk Beyer (Uni Passau, Germany)." + endl); versionText.append("CCVisu is free software, released under the GNU LGPL. " + endl); return versionText.toString(); } /** * Returns a brief tool description. */ public static String toolDescription() { return "CCVisu, a tool for visual graph clustering and " + "general force-directed graph layout."; } /** * Returns data and time in ISO format. */ public static String currentDateTime() { return (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date()); } /** * Returns usage information. */ public String helpMessage() { StringBuilder msg = new StringBuilder(); msg.append(endl); msg.append("This is " + Options.toolDescription() + endl); msg.append(CCVISU_URL + endl); msg.append(endl); msg.append("Usage: java ccvisu.CCVisu [OPTION]..." + endl); msg.append("Compute a layout for a given (co-change) graph (or convert)." + endl); msg.append(endl); msg.append("Options: " + endl); msg.append("General options: " + endl); msg.append(Options.helpForOption(OptionsEnum.help)); msg.append(Options.helpForOption(OptionsEnum.version)); msg.append(Options.helpForOption(OptionsEnum.quiet)); msg.append(Options.helpForOption(OptionsEnum.warnings)); msg.append(Options.helpForOption(OptionsEnum.verbose)); msg.append(Options.helpForOption(OptionsEnum.assertCheck)); msg.append(Options.helpForOption(OptionsEnum.guiMode)); msg.append(Options.helpForOption(OptionsEnum.inputName)); msg.append(Options.helpForOption(OptionsEnum.outputName)); msg.append(" -inFormat FORMAT read input data in format FORMAT (default: RSF, see below)." + endl); msg.append(" -outFormat FORMAT write output data in format FORMAT (default: DISP, see below)." + endl); msg.append(endl); msg.append("Layouting options:" + endl); msg.append(Options.helpForOption(OptionsEnum.dim)); msg.append(Options.helpForOption(OptionsEnum.iter)); msg.append(Options.helpForOption(OptionsEnum.initLayout)); msg.append(Options.helpForOption(OptionsEnum.fixedInitPos)); msg.append(endl); msg.append("Energy model options:" + endl); msg.append(" -attrExp <int> exponent for the distance in the attraction term" + endl); msg.append(" (default: 1)." + endl); msg.append(" -repuExp <int> specifies that <int> is applied as exponent to the distance in the repulsion term" + endl); msg.append(" (if <int> != 0) or that log is applied to the distance (if <int> = 0) (default: 0)." + endl); msg.append(" -vertRepu use vertex repulsion instead of edge repulsion" + endl); msg.append(" (default: edge repulsion). " + endl); msg.append(" -noWeight use unweighted model (default: weighted)." + endl); msg.append(" -grav <float> gravitation factor for the Barnes-Hut-procedure" + endl); msg.append(" (default: 0.001)." + endl); msg.append(endl); msg.append("Dependency visualization options: " + endl); msg.append(Options.helpForOption(OptionsEnum.cdep)); msg.append(Options.helpForOption(OptionsEnum.enableToolTips)); msg.append(endl); msg.append("DOX reader option:" + endl); msg.append(" -relSelect <rel> selects a relation for visualization" + endl); msg.append(" (default: REFFILE). " + endl); msg.append(endl); msg.append("CVS reader options:" + endl); msg.append(Options.helpForOption(OptionsEnum.timeWindow)); msg.append(Options.helpForOption(OptionsEnum.slidingTW)); msg.append(endl); msg.append("SRC reader options: " + endl); msg.append(Options.helpForOption(OptionsEnum.sourceDirectory)); msg.append(Options.helpForOption(OptionsEnum.sourceLibraries)); msg.append(Options.helpForOption(OptionsEnum.sourceBlacklist)); msg.append(endl); msg.append("Layout writer options:" + endl); msg.append(Options.helpForOption(OptionsEnum.hideSource)); msg.append(Options.helpForOption(OptionsEnum.minVert)); msg.append(Options.helpForOption(OptionsEnum.fontSize)); msg.append(" -backColor COLOR background color (default: WHITE)." + endl); msg.append(" Colors: BLACK, GRAY, LIGHTGRAY, WHITE." + endl); msg.append(" -noBlackCircle no black circle around each vertex (default: with). " + endl); msg.append(Options.helpForOption(OptionsEnum.ringColor)); msg.append(Options.helpForOption(OptionsEnum.depDegreeColor)); msg.append(Options.helpForOption(OptionsEnum.enableFeatureVisu)); msg.append(Options.helpForOption(OptionsEnum.showEdges)); msg.append(Options.helpForOption(OptionsEnum.scalePos)); msg.append(" -noAnim layout not shown while minimizer is still improving it " + endl); msg.append(" (default: show). " + endl); msg.append(Options.helpForOption(OptionsEnum.showAllLabels)); msg.append(Options.helpForOption(OptionsEnum.shortNames)); msg.append(Options.helpForOption(OptionsEnum.dispFilter)); msg.append(Options.helpForOption(OptionsEnum.initGroups)); msg.append(Options.helpForOption(OptionsEnum.openURL)); msg.append(endl); msg.append("Clustering (partitioning) options:" + endl); msg.append(Options.helpForOption(OptionsEnum.clusterMinDistancePercent)); msg.append(Options.helpForOption(OptionsEnum.clusters)); msg.append(endl); msg.append("DISP specific option" + endl); msg.append(Options.helpForOption(OptionsEnum.browser)); msg.append(endl); msg.append("Input Formats:" + endl); for (InFormat f : InFormat.values()) { msg.append(Options.helpOptionNameIndent(" " + f.toString() + " ") + f.getDescription() + endl); } msg.append("Output Formats:" + endl); for (OutFormat f : OutFormat.values()) { msg.append(Options.helpOptionNameIndent(" " + f.toString() + " ") + f.getDescription() + endl); } msg.append(endl); msg.append(CCVISU_URL + endl); msg.append(endl); msg.append(endl); msg.append("Report bugs to Dirk Beyer <firstname.lastname@uni-passau.de>." + endl); return msg.toString(); } private static String helpForOption(OptionsEnum option) { String argText = ""; if (option.getType().equals("Integer")) { argText = " <int>"; } if (option.getType().equals("Float")) { argText = " <float>"; } if (option.getType().equals("String")) { argText = " <str>"; } String lOption = "-" + option.toString(); if (!option.altOptName.equals("") && option.type.equals("Boolean")) { lOption = "-" + option.altOptName + " --" + option.toString(); } return Options.helpOptionNameIndent(" " + lOption + argText + " ") + option.getDescription() + " (default value: " + option.getDefault() + "). " + endl; } private static String helpOptionNameIndent(String string) { String indent = " "; if (string.length() >= indent.length()) { return string; } return string + indent.substring(string.length(), indent.length()); } /** * Transforms the format given as a string into the appropriate enum. * @param formatStr File format string to be converted to enum. * @return File format identifier. */ private static InFormat getInFormat(String formatStr) { InFormat result = InFormat.RSF; try { result = InFormat.valueOf(formatStr.toUpperCase()); } catch (Exception e) { Options.handleFormatException(formatStr); } return result; } /** * Get input format of file by extension. * @param fileName * @return Format. */ public static InFormat getInFormatOfFile(String fileName) { for (InFormat f: InFormat.values()) { if (fileName.endsWith(f.fileExtension)) { return f; } } return InFormat.RSF; } /** * Get output format by file extension. * * @param fileExtension * @return Format. */ public static OutFormat getOutFormatByExtension(String fileExtension) { for (OutFormat f : OutFormat.values()) { if ((fileExtension).equalsIgnoreCase(f.getFileExtension())) { return f; } } return OutFormat.NULL; } /** * Transforms the format given as a string into the appropriate enum. * @param formatStr File format string to be converted to enum. * @return File format identifier. */ private static OutFormat getOutFormat(String formatStr) { OutFormat result = OutFormat.RSF; try { result = OutFormat.valueOf(formatStr.toUpperCase()); } catch (Exception e) { Options.handleFormatException(formatStr); } return result; } /** * Handles exceptions of format conversions. * @param formatStr input/output format as string */ private static void handleFormatException(String formatStr) { System.err.println("Usage error: '" + formatStr + "' is not a valid input/output format."); System.exit(1); } }