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

org.basinmc.plunger.mapping.csv.CSVParameterNameMappingParser Maven / Gradle / Ivy

There is a newer version: 3.0
Show newest version
/*
 * Copyright 2018 Johannes Donath 
 * and other copyright owners as documented in the project's IP log.
 *
 * 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 org.basinmc.plunger.mapping.csv;

import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.basinmc.plunger.mapping.ParameterNameMapping;

/**
 * Provides a parser for CSV based parameter name mappings.
 *
 * @author Johannes Donath
 */
public final class CSVParameterNameMappingParser extends
    AbstractCSVMappingParser {

  private final String classNameColumn;
  private final String methodNameColumn;
  private final String parameterIndexColumn;
  private final String parameterNameColumn;
  private final String signatureColumn;
  private final String targetNameColumn;

  CSVParameterNameMappingParser(
      @NonNull CSVFormat format,
      @Nullable String classNameColumn,
      @Nullable String methodNameColumn,
      @Nullable String signatureColumn,
      @Nullable String parameterNameColumn,
      @Nullable String parameterIndexColumn,
      @NonNull String targetNameColumn) {
    super(format);

    if (parameterIndexColumn == null && parameterNameColumn == null) {
      throw new IllegalArgumentException(
          "Illegal configuration: Either parameter name or parameter index column is required");
    }

    this.classNameColumn = classNameColumn;
    this.methodNameColumn = methodNameColumn;
    this.signatureColumn = signatureColumn;
    this.parameterNameColumn = parameterNameColumn;
    this.parameterIndexColumn = parameterIndexColumn;
    this.targetNameColumn = targetNameColumn;
  }

  /**
   * Constructs a new empty factory for parameter name mapping instances.
   *
   * @return a factory.
   */
  @NonNull
  public static Builder builder() {
    return new Builder();
  }

  /**
   * {@inheritDoc}
   */
  @Override
  protected ParameterNameMapping doParse(@NonNull CSVParser parser) throws IOException {
    ParameterNameMappingImpl mapping = new ParameterNameMappingImpl(
        this.parameterNameColumn != null);
    mapping.entries.addAll(
        parser.getRecords().stream()
            .map((r) -> new ParameterNameMappingEntry(
                this.classNameColumn != null ? r.get(this.classNameColumn) : null,
                this.methodNameColumn != null ? r.get(this.methodNameColumn) : null,
                this.signatureColumn != null ? r.get(this.signatureColumn) : null,
                this.parameterNameColumn != null ? r.get(this.parameterNameColumn) : null,
                this.parameterIndexColumn != null ? Integer
                    .parseUnsignedInt(r.get(this.parameterIndexColumn)) : null,
                r.get(this.targetNameColumn)
            ))
            .collect(Collectors.toSet())
    );
    return mapping;
  }

  /**
   * Provides a factory for parameter name mapping parser instances.
   */
  public static final class Builder extends AbstractCSVMappingParser.MemberBuilder {

    private String methodNameColumn;
    private String parameterIndexColumn;
    private String parameterNameColumn;
    private String signatureColumn;

    private Builder() {
    }

    /**
     * Constructs a new CSV parameter name mapping parser based on the current builder
     * configuration.
     *
     * @param targetNameColumn a target name column index.
     * @return a name mapping parser.
     * @throws IllegalStateException when neither parameterNameColumn or parameterIndexColumn are
     * defined.
     */
    @NonNull
    public CSVParameterNameMappingParser build(@NonNull String targetNameColumn) {
      if (this.parameterNameColumn == null && this.parameterIndexColumn == null) {
        throw new IllegalStateException(
            "Illegal configuration: Either of parameterNameColumn or parameterIndexColumn needs to be defined");
      }

      return new CSVParameterNameMappingParser(
          this.format,
          this.classNameColumn,
          this.methodNameColumn,
          this.signatureColumn,
          this.parameterNameColumn,
          this.parameterIndexColumn,
          targetNameColumn
      );
    }

    /**
     * {@inheritDoc}
     */
    @NonNull
    @Override
    public Builder withClassNameColumn(@Nullable String columnName) {
      super.withClassNameColumn(columnName);
      return this;
    }

    /**
     * {@inheritDoc}
     */
    @NonNull
    @Override
    public Builder withFormat(@NonNull CSVFormat format) {
      super.withFormat(format);
      return this;
    }

    /**
     * 

Selects the column in which the method name will be found.

* *

If none is specified (e.g. this method is not called at all or null is passed), the * resulting mapper will only evaluate whether or not the method name, class name and parameter * name/index match (assuming that a class name and signature name index was configured).

* * @param columnName a column index. * @return a reference to this builder. */ @NonNull public Builder withMethodNameColumn(@Nullable String columnName) { this.methodNameColumn = columnName; return this; } /** * Selects the column in which the original parameter index will be found. * * @param columnName a column index. * @return a reference to this builder. */ @NonNull public Builder withParameterIndexColumn(@Nullable String columnName) { this.parameterIndexColumn = columnName; return this; } /** * Selects the column in which the original parameter name will be found. * * @param columnName a column index. * @return a reference to this builder. */ @NonNull public Builder withParameterNameColumn(@Nullable String columnName) { this.parameterNameColumn = columnName; return this; } /** *

Selects the column in which the ASM signature for the method will be found.

* *

If none is specified (e.g. this method is not called at all or null is passed), the * resulting mapper will only evaluate whether or not the method name and class name match * (assuming that a class name index was configured).

* * @param columnName a column index. * @return a reference to this builder. */ @NonNull public Builder withSignatureColumn(@Nullable String columnName) { this.signatureColumn = columnName; return this; } } /** * Represents a single parsed parameter name entry. */ private static final class ParameterNameMappingEntry { private final String className; private final String methodName; private final Integer parameterIndex; private final String parameterName; private final String signature; private final String targetName; private ParameterNameMappingEntry( @Nullable String className, @Nullable String methodName, @Nullable String signature, @Nullable String parameterName, @Nullable Integer parameterIndex, @NonNull String targetName) { this.className = className; this.methodName = methodName; this.signature = signature; this.parameterName = parameterName; this.parameterIndex = parameterIndex; this.targetName = targetName; assert this.parameterName != null || this.parameterIndex != null; } @NonNull public String getTargetName() { return this.targetName; } public boolean matches(@NonNull String className, @NonNull String methodName, @NonNull String signature, @NonNull String parameterName, int parameterIndex) { if (this.className != null && !this.className.equals(className)) { return false; } if (this.methodName != null && !this.methodName.equals(methodName)) { return false; } if (this.signature != null && !this.signature.equals(signature)) { return false; } if (this.parameterName != null) { return this.parameterName.equals(parameterName); } assert this.parameterIndex != null; return this.parameterIndex == parameterIndex; } } /** * Provides a parsed representation of a parameter name mapping. */ private static final class ParameterNameMappingImpl implements ParameterNameMapping { private final Collection entries = new HashSet<>(); private final boolean nameAvailable; private ParameterNameMappingImpl(boolean nameAvailable) { this.nameAvailable = nameAvailable; } /** * {@inheritDoc} */ @NonNull @Override public Optional getParameterName(@NonNull String className, @NonNull String methodName, @NonNull String signature, @Nullable String parameterName, int parameterIndex) { return this.entries.stream() .filter((e) -> e.matches(className, methodName, signature, parameterName, parameterIndex)) .findAny() .map(ParameterNameMappingEntry::getTargetName); } /** * {@inheritDoc} */ @NonNull @Override public ParameterNameMapping invert() { if (!this.nameAvailable) { throw new UnsupportedOperationException(); } ParameterNameMappingImpl mapping = new ParameterNameMappingImpl(true); mapping.entries.addAll( mapping.entries.stream() .map((e) -> { assert e.parameterName != null; return new ParameterNameMappingEntry(e.className, e.methodName, e.signature, e.targetName, null, e.parameterName); }) .collect(Collectors.toSet()) ); return mapping; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy