org.apache.openmeetings.cli.OmHelpFormatter.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.openmeetings.cli.OmHelpFormatter.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License") +  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.openmeetings.cli;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;

public class OmHelpFormatter extends HelpFormatter {
    private static String GENERAL_OPTION_GROUP = "";
    private int maxPrefixLength = 0;

    @SuppressWarnings("unchecked")
    private static List<OmOption> getReqOptions(Options opts) {
        //suppose we have only 1 group (for now)
        OptionGroup g = ((List<OptionGroup>) opts.getRequiredOptions()).get(0);
        List<OmOption> result = new ArrayList<OmOption>();
        for (Option o : g.getOptions()) {
            result.add((OmOption) o);
        }
        Collections.sort(result, new Comparator<OmOption>() {
            @Override
            public int compare(OmOption o1, OmOption o2) {
                return o1.getOrder() - o2.getOrder();
            }
        });
        return result;
    }

    private LinkedHashMap<String, List<OmOption>> getOptions(Options opts, int leftPad) {
        final String longOptSeparator = " ";
        final String lpad = createPadding(leftPad);
        final String lpadParam = createPadding(leftPad + 2);
        List<OmOption> reqOptions = getReqOptions(opts);
        LinkedHashMap<String, List<OmOption>> map = new LinkedHashMap<String, List<OmOption>>(reqOptions.size());
        map.put(GENERAL_OPTION_GROUP, new ArrayList<OmOption>());
        for (OmOption o : reqOptions) {
            map.put(o.getOpt(), new ArrayList<OmOption>());
        }
        for (Option _o : opts.getOptions()) {
            OmOption o = (OmOption) _o;
            //TODO need better check (required option should go first and should not be duplicated
            boolean skipOption = map.containsKey(o.getOpt());
            boolean mainOption = skipOption || o.getGroup() == null;

            // first create list containing only <lpad>-a,--aaa where
            // -a is opt and --aaa is long opt; in parallel look for
            // the longest opt string this list will be then used to
            // sort options ascending
            StringBuilder optBuf = new StringBuilder();
            if (o.getOpt() == null) {
                optBuf.append(mainOption ? lpad : lpadParam).append("   ").append(getLongOptPrefix())
                        .append(o.getLongOpt());
            } else {
                optBuf.append(mainOption ? lpad : lpadParam).append(getOptPrefix()).append(o.getOpt());

                if (o.hasLongOpt()) {
                    optBuf.append(',').append(getLongOptPrefix()).append(o.getLongOpt());
                }
            }

            if (o.hasArg()) {
                String argName = o.getArgName();
                if (argName != null && argName.length() == 0) {
                    // if the option has a blank argname
                    optBuf.append(' ');
                } else {
                    optBuf.append(o.hasLongOpt() ? longOptSeparator : " ");
                    optBuf.append("<").append(argName != null ? o.getArgName() : getArgName()).append(">");
                }
            }

            o.setHelpPrefix(optBuf);
            maxPrefixLength = Math.max(optBuf.length(), maxPrefixLength);

            if (skipOption) {
                //TODO need better check (required option should go first and should not be duplicated
                continue;
            }
            String grp = o.getGroup();
            grp = grp == null ? GENERAL_OPTION_GROUP : grp;
            String[] grps = grp.split(",");
            for (String g : grps) {
                map.get(g).add(o);
            }
        }
        for (Map.Entry<String, List<OmOption>> me : map.entrySet()) {
            final String key = me.getKey();
            List<OmOption> options = me.getValue();
            Collections.sort(options, new Comparator<OmOption>() {
                @Override
                public int compare(OmOption o1, OmOption o2) {
                    boolean o1opt = !o1.isOptional(key);
                    boolean o2opt = !o2.isOptional(key);
                    return (o1opt && o2opt || !o1opt && !o2opt) ? (o1.getOpt() == null ? 1 : -1) : (o1opt ? -1 : 1);
                }

            });
            if (opts.hasOption(key)) {
                options.add(0, (OmOption) opts.getOption(key));
            }
        }
        return map;
    }

    private static StringBuilder getReqOptionsString(Options opts) {
        String delim = "";
        StringBuilder result = new StringBuilder();
        for (Option o : getReqOptions(opts)) {
            result.append(delim).append("-").append(o.getOpt());
            delim = "|";
        }
        return result;
    }

    @Override
    protected StringBuffer renderOptions(StringBuffer sb, int width, Options options, int leftPad, int descPad) {
        final String dpad = createPadding(descPad);
        final String optional = "(optional) ";

        LinkedHashMap<String, List<OmOption>> optList = getOptions(options, leftPad);

        char[] delimiter = new char[width - 2];
        Arrays.fill(delimiter, '-');

        for (Entry<String, List<OmOption>> me : optList.entrySet()) {
            if (GENERAL_OPTION_GROUP.equals(me.getKey())) {
                sb.append("General options:").append(getNewLine());
            }
            for (OmOption option : me.getValue()) {
                StringBuilder optBuf = new StringBuilder(option.getHelpPrefix());

                if (optBuf.length() < maxPrefixLength) {
                    optBuf.append(createPadding(maxPrefixLength - optBuf.length()));
                }

                optBuf.append(dpad);

                int nextLineTabStop = maxPrefixLength + descPad;

                if (option.isOptional(me.getKey())) {
                    optBuf.append(optional);
                }
                if (option.getDescription() != null) {
                    optBuf.append(option.getDescription());
                }

                renderWrappedText(sb, width, nextLineTabStop, optBuf.toString());

                sb.append(getNewLine());
            }
            sb.append(delimiter).append(getNewLine());
        }
        return sb;
    }

    @Override
    public void printHelp(PrintWriter pw, int width, String cmdLineSyntax, String header, Options options,
            int leftPad, int descPad, String footer, boolean autoUsage) {
        if ((cmdLineSyntax == null) || (cmdLineSyntax.length() == 0)) {
            throw new IllegalArgumentException("cmdLineSyntax not provided");
        }

        printUsage(pw, width, cmdLineSyntax, options);

        if ((header != null) && (header.trim().length() > 0)) {
            printWrapped(pw, width, header);
        }

        printOptions(pw, width, options, leftPad, descPad);

        if ((footer != null) && (footer.trim().length() > 0)) {
            printWrapped(pw, width, footer);
        }
    }

    @Override
    public void printUsage(PrintWriter pw, int width, String app, Options opts) {
        pw.println(String.format("usage: %1$s [%2$s] [options]", app, getReqOptionsString(opts)));
    }
}