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

com.joliciel.talismane.machineLearning.features.FunctionDescriptor Maven / Gradle / Ivy

There is a newer version: 6.1.8
Show newest version
///////////////////////////////////////////////////////////////////////////////
//Copyright (C) 2014 Joliciel Informatique
//
//This file is part of Talismane.
//
//Talismane is free software: you can redistribute it and/or modify
//it under the terms of the GNU Affero General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//Talismane 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 Affero General Public License for more details.
//
//You should have received a copy of the GNU Affero General Public License
//along with Talismane.  If not, see .
//////////////////////////////////////////////////////////////////////////////
package com.joliciel.talismane.machineLearning.features;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.joliciel.talismane.utils.JolicielException;

/**
 * A textual descriptor of a function, used for parsing a list of textual
 * function descriptors.
 * 
 * @author Assaf Urieli
 *
 */
public class FunctionDescriptor {
  enum FunctionDescriptorType {
    Function,
    Argument
  }

  private static final Logger LOG = LoggerFactory.getLogger(FunctionDescriptor.class);

  String functionName = null;
  List arguments = new ArrayList();
  Object object = null;
  String descriptorName = null;
  boolean binaryOperator = false;
  boolean empty = false;
  FunctionDescriptor parent;
  String groupName = null;

  /**
   * Get a function descriptor that wraps an actual function of the given name.
   */
  public FunctionDescriptor(String functionName) {
    this(functionName, FunctionDescriptorType.Function);
  }

  /**
   * If type=Argument, construct a function descriptor that simply wraps an
   * object, however, this argument is described by the argument provided as a
   * string. If it can be parsed as an int, and doesn't contain a ".", the
   * wrapped object will be an int. If it can be parsed as a double, the wrapped
   * object will be a double. If it can be parsed as a boolean, the wrapped
   * object will be a boolean. Otherwise, assumes it's a function name.
   */
  FunctionDescriptor(String name, FunctionDescriptorType type) {
    if (type == FunctionDescriptorType.Function)
      this.setFunctionName(name);
    else {
      this.setObjectAsString(name);
    }
  }

  /**
   * Get a function descriptor that simply wraps an object, rather than an
   * actual function.
   */
  FunctionDescriptor(Object object, boolean isObject) {
    if (!isObject)
      throw new JolicielException("the boolean argument is just for differentiating constructors!");
    this.object = object;
  }

  FunctionDescriptor(FunctionDescriptor toClone) {
    if (toClone.isFunction()) {
      this.setFunctionName(toClone.getFunctionName());
      if (toClone.isBinaryOperator())
        this.setBinaryOperator(true);
      for (FunctionDescriptor argument : toClone.getArguments()) {
        this.addArgument(argument.cloneDescriptor());
      }
    } else {
      this.setObject(toClone.getObject());
    }
    this.setGroupName(toClone.getGroupName());
  }

  /**
   * The function name when this descriptor describes a function, otherwise
   * null.
   */
  public String getFunctionName() {
    return functionName;
  }

  public void setFunctionName(String functionName) {
    if (this.object != null)
      throw new RuntimeException("Descriptor cannot be both a literal and a function");

    this.functionName = functionName;
    if (functionName.length() == 0)
      empty = true;
  }

  /**
   * The list of arguments when this descriptor describes a function.
   */
  public List getArguments() {
    return arguments;
  }

  /**
   * Like addArgument(Object), but adds the argument at a particular index.
   */
  public void addArgument(int index, Object argument) {
    if (argument == null)
      throw new RuntimeException("Cannot add a null argument!");

    FunctionDescriptor argumentFunction = null;
    if (argument instanceof FunctionDescriptor)
      argumentFunction = (FunctionDescriptor) argument;
    else
      argumentFunction = new FunctionDescriptor(argument, true);

    if (index < 0)
      arguments.add(argumentFunction);
    else
      arguments.add(index, argumentFunction);

    if (LOG.isTraceEnabled())
      LOG.trace("Add argument: " + this.toString());

    argumentFunction.setParent(this);
  }

  /**
   * Add an argument to this descriptor (at the end of the argument list). If
   * the argument is a FunctionDescriptor, will get added as is. Otherwise, will
   * get added as FunctionDescriptor wrapper to the argument provided.
   */
  public void addArgument(Object argument) {
    this.addArgument(-1, argument);
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    if (this.functionName != null) {
      sb.append(this.functionName);
      sb.append("(");
    } else if (this.object != null) {
      if (this.object instanceof String)
        sb.append("\"" + this.object.toString() + "\"");
      else
        sb.append(this.object.toString());
    }
    if (this.arguments.size() > 0) {
      boolean firstArgument = true;
      for (FunctionDescriptor argument : arguments) {
        if (!firstArgument)
          sb.append(",");
        sb.append(argument.toString());
        firstArgument = false;
      }
    }
    if (this.functionName != null) {
      sb.append(")");
    }
    return sb.toString();
  }

  /**
   * When this function descriptor describes an object, rather than a function,
   * the object it describes. Otherwise null.
   */
  public Object getObject() {
    return object;
  }

  public void setObject(Object object) {
    if (this.functionName != null)
      throw new RuntimeException("Descriptor cannot be both a function and a literal");
    this.object = object;
  }

  public void setObjectAsString(String argumentString) {
    if (this.object == null) {
      if (argumentString.contains(".")) {
        try {
          double doubleArgument = Double.parseDouble(argumentString);
          this.setObject(doubleArgument);
        } catch (NumberFormatException nfe) {
          // nothing to do here
        }
      }
    }

    if (this.object == null) {
      try {
        int intArgument = Integer.parseInt(argumentString);
        this.setObject(intArgument);
      } catch (NumberFormatException nfe) {
        // nothing to do here
      }
    }

    if (this.object == null) {
      if (argumentString.equals("true")) {
        this.setObject(true);
      } else if (argumentString.equals("false")) {
        this.setObject(false);
      }
    }

    if (this.object == null) {
      // assume it's a function not followed by parentheses
      this.functionName = argumentString;
    }
  }

  /**
   * A name given to this descriptor, or null otherwise.
   */
  public String getDescriptorName() {
    return descriptorName;
  }

  public void setDescriptorName(String descriptorName) {
    this.descriptorName = descriptorName;
  }

  /**
   * Returns true if function, false if literal.
   */
  public boolean isFunction() {
    return this.object == null;
  }

  /**
   * Is this descriptor a binary operator?
   */
  public boolean isBinaryOperator() {
    return binaryOperator;
  }

  public void setBinaryOperator(boolean binaryOperator) {
    this.binaryOperator = binaryOperator;
  }

  /**
   * Is this descriptor an empty function (without a name, typically
   * corresponding to open parenthesis).
   */
  public boolean isEmpty() {
    return empty;
  }

  /**
   * This function descriptor's parent.
   */
  public FunctionDescriptor getParent() {
    return parent;
  }

  void setParent(FunctionDescriptor parent) {
    this.parent = parent;
  }

  /**
   * Deep clone this function descriptor.
   */
  public FunctionDescriptor cloneDescriptor() {
    FunctionDescriptor descriptor = new FunctionDescriptor(this);
    return descriptor;
  }

  /**
   * Replace a given named parameter (basically a placeholder) within this
   * function descriptor by an actual argument value (a function descriptor to
   * put instead of the placeholder).
   */
  public void replaceParameter(String parameterName, FunctionDescriptor argument) {
    List replaceIndexes = new ArrayList();

    int i = 0;
    for (FunctionDescriptor descriptor : this.getArguments()) {
      if (descriptor.isFunction() && descriptor.getFunctionName().equals(parameterName)) {
        replaceIndexes.add(i);
      }
      i++;
    }
    for (int index : replaceIndexes) {
      this.getArguments().remove(index);
      this.getArguments().add(index, argument);
    }
    i = 0;
    for (FunctionDescriptor descriptor : this.getArguments()) {
      if (replaceIndexes.contains(i))
        continue;
      descriptor.replaceParameter(parameterName, argument);
      i++;
    }
  }

  /**
   * The name of the group to which this descriptor belongs, or null otherwise.
   * Several descriptors can be grouped together in a group, for mutual handling
   * downstream by other descriptors.
   */
  public String getGroupName() {
    return groupName;
  }

  public void setGroupName(String groupName) {
    this.groupName = groupName;
  }

  /**
   * Was this descriptor defined at the top level (a line of its own), or is it
   * inside another descriptor.
   */
  public boolean isTopLevelDescriptor() {
    return this.getParent() == null;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy