PropertyImpl.java

/*
 * Copyright (c) 2016, Stein Eldar Johnsen
 *
 * 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 net.morimekta.terminal.args.impl;

import net.morimekta.terminal.args.ArgException;
import net.morimekta.terminal.args.Property;

import java.util.List;

/**
 * A property is an option where the value is a key-value pair, and applies
 * the key value onto a putter.
 */
public class PropertyImpl extends BaseOption implements Property {
    @Override
    public String getMetaKey() {
        return metaKey;
    }

    @Override
    public String getSingleLineUsage() {
        if (getShortNames().isEmpty()) {
            return "[" +
                   getName() +
                   " " +
                   metaKey +
                   '=' +
                   getMetaVar() +
                   " ...]";
        } else {
            return "[-" +
                   getShortNames() +
                   metaKey +
                   '=' +
                   getMetaVar() +
                   " ...]";
        }
    }

    @Override
    public String getPrefix() {
        if (getShortNames().isEmpty()) {
            return getName() +
                   " " +
                   metaKey +
                   '=' +
                   getMetaVar();
        } else if (getName() == null) {
            return '-' +
                   getShortNames() +
                   metaKey +
                   '=' +
                   getMetaVar();
        } else {
            return getName() +
                   " (-" + getShortNames() +
                   ") " +
                   metaKey +
                   '=' +
                   getMetaVar();
        }
    }

    @Override
    public void validate() throws ArgException {
    }

    @Override
    public int applyShort(String opts, List<String> args) {
        if (opts.length() == 1) {
            return apply(args);
        }

        String[] parts = opts.substring(1).split("=", 2);
        if (parts.length != 2) {
            throw new ArgException("No key value sep for properties on %s: \"-%s\"",
                                   nameOrShort(), opts);
        }
        if (parts[0].length() == 0) {
            throw new ArgException("Empty property key on %s: \"-%s\"",
                                   nameOrShort(), opts);
        }
        properties.put(parts[0], parts[1]);
        return 1;
    }

    @Override
    public int apply(List<String> args) {
        if (args.size() < 2) {
            throw new ArgException("No value for %s", nameOrShort());
        }
        String[] parts = args.get(1).split("=", 2);
        if (parts.length != 2) {
            throw new ArgException("No key value sep for properties on %s: \"%s\"",
                                   nameOrShort(), args.get(1));
        }
        if (parts[0].length() == 0) {
            throw new ArgException("Empty property key on %s: \"%s\"",
                                   nameOrShort(), args.get(1));
        }
        properties.put(parts[0], parts[1]);
        return 2;
    }

    public static class BuilderImpl implements Property.Builder {
        private final String    name;
        private final Character shortChar;
        private final String    usage;
        private final Putter    properties;
        private       String    metaKey;
        private       String    metaVar;
        private       boolean   hidden;

        public BuilderImpl(String name, Character shortChar, String usage, Putter properties) {
            this.name = name;
            this.shortChar = shortChar;
            this.usage = usage;
            this.properties = properties;
            this.metaKey = "key";
            this.metaVar("val");
        }

        @Override
        public Property build() {
            return new PropertyImpl(name, shortChar, metaKey, metaVar, usage, properties, hidden);
        }

        @Override
        public BuilderImpl metaKey(String metaKey) {
            this.metaKey = metaKey;
            return this;
        }

        @Override
        public BuilderImpl metaVar(String metaVar) {
            this.metaVar = metaVar;
            return this;
        }

        @Override
        public BuilderImpl hidden() {
            this.hidden = true;
            return this;
        }
    }

    // --- PRIVATE ---

    private final Property.Putter properties;
    private final String          metaKey;

    private PropertyImpl(String name,
                         Character shortChar,
                         String metaKey,
                         String metaVar,
                         String usage,
                         Putter properties,
                         boolean hidden) {
        super(name,   // long-option name
              shortChar == null ? null : String.valueOf(shortChar),
              metaVar == null ? "val" : metaVar,
              usage,
              null,   // default value
              true,   // repeated
              false,  // required
              hidden);
        this.metaKey = metaKey == null ? "key" : metaKey;
        this.properties = properties;
    }
}