All Downloads are FREE. Search and download functionalities are using the official Maven repository.

co.cask.wrangler.api.parser.UsageDefinition Maven / Gradle / Ivy

There is a newer version: 3.2.2
Show newest version
/*
 * Copyright © 2017 Cask Data, Inc.
 *
 * Licensed 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 co.cask.wrangler.api.parser;

import co.cask.wrangler.api.Optional;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * This class {@link UsageDefinition} provides a way for users to registers the argument for UDDs.
 *
 * {@link UsageDefinition} is a collection of {@link TokenDefinition} and the name of the directive
 * itself. Each token specification has an associated ordinal that can be used to position the argument
 * within the directive.
 *
 * Following is a example of how this class can be used.
 * 
 *   UsageDefinition.Builder builder = UsageDefinition.builder();
 *   builder.add("col1", TypeToken.COLUMN_NAME); // By default, this field is required.
 *   builder.add("col2", TypeToken.COLUMN_NAME, false); // This is a optional field.
 *   builder.add("expression", TypeToken.EXPRESSION);
 *   UsageDefinition definition = builder.build();
 * 
 *
 * NOTE: No constraints checks are included in this implementation.
 *
 * @see TokenDefinition
 */
public final class UsageDefinition implements Serializable {
  private final int optionalCnt;
  private String directive;
  private final List tokens;

  private UsageDefinition(String directive, int optionalCnt, List tokens) {
    this.directive = directive;
    this.tokens = tokens;
    this.optionalCnt = optionalCnt;
  }

  /**
   * Returns the name of the directive for which the this UsageDefinition
   * object is created.
   *
   * @return name of the directive.
   */
  public String getDirectiveName() {
    return directive;
  }

  /**
   * This method returns the list of TokenDefinition that should be
   * used for parsing the directive into Arguments.
   *
   * @return List of TokenDefinition.
   */
  public List getTokens() {
    return tokens;
  }

  /**
   * Returns the count of TokenDefinition that have been specified
   * as optional in the UsageDefinition.
   *
   * @return number of tokens in the usage that are optional.
   */
  public int getOptionalTokensCount() {
    return optionalCnt;
  }

  /**
   * This method converts the UsageDefinition into a usage string
   * for this directive. It inspects all the tokens to generate a standard syntax
   * for the usage of the directive.
   *
   * @return a usage representation of this object.
   */
  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append(directive).append(" ");

    int count = tokens.size();
    for (TokenDefinition token : tokens) {
      if(token.optional()) {
        sb.append(" [");
      }

      if(token.label() != null) {
        sb.append(token.label());
      } else {
        if (token.type().equals(TokenType.DIRECTIVE_NAME)) {
          sb.append(token.name());
        } else if (token.type().equals(TokenType.COLUMN_NAME)) {
          sb.append(":").append(token.name());
        } else if (token.type().equals(TokenType.COLUMN_NAME_LIST)) {
          sb.append(":").append(token.name()).append(" [,:").append(token.name()).append("  ]*");
        } else if (token.type().equals(TokenType.BOOLEAN)) {
          sb.append(token.name()).append(" (true/false)");
        } else if (token.type().equals(TokenType.TEXT)) {
          sb.append("'").append(token.name()).append("'");
        } else if (token.type().equals(TokenType.IDENTIFIER) || token.type().equals(TokenType.NUMERIC)) {
          sb.append(token.name());
        } else if (token.type().equals(TokenType.BOOLEAN_LIST) || token.type().equals(TokenType.NUMERIC_LIST)
          || token.type().equals(TokenType.TEXT_LIST)) {
          sb.append(token.name()).append("[,").append(token.name()).append(" ...]*");
        } else if (token.type().equals(TokenType.EXPRESSION)) {
          sb.append("exp:{<").append(token.name()).append(">}");
        } else if (token.type().equals(TokenType.PROPERTIES)) {
          sb.append("prop:{key:value,[key:value]*");
        } else if (token.type().equals(TokenType.RANGES)) {
          sb.append("start:end=[bool|text|numeric][,start:end=[bool|text|numeric]*");
        }
      }

      count--;

      if(token.optional()) {
        sb.append("]");
      } else {
        if (count > 0) {
          sb.append(" ");
        }
      }
    }
    return sb.toString();
  }

  /**
   * This method provides a JsonElement object for this UsageDefinition
   * object.
   *
   * @return A instance of JsonElement representing the state of this object.
   */
  public JsonElement toJson() {
    JsonObject object = new JsonObject();
    object.addProperty("directive", directive);
    JsonArray array = new JsonArray();
    for (TokenDefinition token : tokens) {
      array.add(token.toJson());
    }
    object.add("tokens", array);
    return object;
  }

  /**
   * This is a static method for creating a builder for the UsageDefinition
   * object. In order to create a UsageDefinition, a builder has to created.
   *
   * 

This builder is provided as user API for constructing the usage specification * for a directive.

* * @param directive name of the directive for which the builder is created for. * @return A UsageDefinition.Builder object that can be used to construct * UsageDefinition object. */ public static UsageDefinition.Builder builder(String directive) { return new UsageDefinition.Builder(directive); } /** * This inner builder class provides a way to create UsageDefinition * object. It exposes different methods that allow users to configure the TokenDefinition * for each token used within the usage of a directive. */ public static final class Builder { private String directive; private final List tokens; private int currentOrdinal; private int optionalCnt; public Builder(String directive) { this.directive = directive; this.currentOrdinal = 0; this.tokens = new ArrayList<>(); this.optionalCnt = 0; } /** * This method provides a way to set the name and the type of token, while * defaulting the label to 'null' and setting the optional to FALSE. * * @param name of the token in the definition of a directive. * @param type of the token to be extracted. */ public void define(String name, TokenType type) { TokenDefinition spec = new TokenDefinition(name, type, null, currentOrdinal, Optional.FALSE); currentOrdinal++; tokens.add(spec); } /** * Allows users to define a token with a name, type of the token and additional optional * for the label that is used during creation of the usage for the directive. * * @param name of the token in the definition of a directive. * @param type of the token to be extracted. * @param label label that modifies the usage for this field. */ public void define(String name, TokenType type, String label) { TokenDefinition spec = new TokenDefinition(name, type, label, currentOrdinal, Optional.FALSE); currentOrdinal++; tokens.add(spec); } /** * Method allows users to specify a field as optional in combination to the * name of the token and the type of token. * * @param name of the token in the definition of a directive. * @param type of the token to be extracted. * @param optional Optional#TRUE if token is optional, else Optional#FALSE. */ public void define(String name, TokenType type, boolean optional) { TokenDefinition spec = new TokenDefinition(name, type, null, currentOrdinal, optional); optionalCnt = optional ? optionalCnt + 1 : optionalCnt; currentOrdinal++; tokens.add(spec); } /** * Method allows users to specify a field as optional in combination to the * name of the token, the type of token and also the ability to specify a label * for the usage. * * @param name of the token in the definition of a directive. * @param type of the token to be extracted. * @param label label that modifies the usage for this field. * @param optional Optional#TRUE if token is optional, else Optional#FALSE. */ public void define(String name, TokenType type, String label, boolean optional) { TokenDefinition spec = new TokenDefinition(name, type, label, currentOrdinal, optional); optionalCnt = optional ? optionalCnt + 1 : optionalCnt; currentOrdinal++; tokens.add(spec); } /** * @return a instance of UsageDefinition object. */ public UsageDefinition build() { return new UsageDefinition(directive, optionalCnt, tokens); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy