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

com.google.api.tools.framework.model.FieldSelector Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2016 Google 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 com.google.api.tools.framework.model;

import com.google.common.base.CaseFormat;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;

import java.util.Iterator;
import java.util.Objects;

/**
 * Represents a field selector, a list of fields with some special operations on it.
 */
public class FieldSelector {

  private static final Splitter FIELD_PATH_SPLITTER = Splitter.on('.');
  private static final Joiner FIELD_PATH_JOINER = Joiner.on('.');

  /**
   * Construct an empty field selector.
   */
  public static FieldSelector of() {
    return new FieldSelector(ImmutableList.of());
  }

  /**
   * Construct a field selector for the given field.
   */
  public static FieldSelector of(Field field) {
    return new FieldSelector(ImmutableList.of(field));
  }

  /**
   * Construct a field selector for the given fields.
   */
  public static FieldSelector of(ImmutableList fields) {
    return new FieldSelector(fields);
  }

  /**
   * Construct a field selector by resolving a field path (as in 'a.b.c') against a message. Returns
   * null if resolution fails.
   */
  public static FieldSelector resolve(MessageType message, String fieldPath) {
    Iterator path = FIELD_PATH_SPLITTER.split(fieldPath).iterator();
    ImmutableList.Builder fieldsBuilder = ImmutableList.builder();

    MessageType currMessage = message;
    while (path.hasNext()) {
      String fieldName = path.next();
      Field field = currMessage.lookupField(fieldName);
      if (field == null) {
        return null;
      }
      fieldsBuilder.add(field);
      if (path.hasNext()) {
        if (!field.getType().isMessage()) {
          return null;
        }
        currMessage = field.getType().getMessageType();
      }
    }

    return new FieldSelector(fieldsBuilder.build());
  }

  public static boolean hasSinglePathElement(String path) {
    return !path.isEmpty() && !path.contains(".");
  }

  private final ImmutableList fields;
  private volatile String paramName;

  private FieldSelector(ImmutableList fields) {
    this.fields = fields;
  }

  /**
   * Returns the fields of this selector.
   */
  public ImmutableList getFields() {
    return fields;
  }

  /**
   * Returns the last field of the selector.
   */
  public Field getLastField() {
    return fields.get(fields.size() - 1);
  }

  /**
   * Returns the type of this field selector, i.e. the type of the last field in the field list.
   */
  public TypeRef getType() {
    return getLastField().getType();
  }

  /**
   * Extend the selector by the field.
   */
  public FieldSelector add(Field field) {
    return new FieldSelector(ImmutableList.builder().addAll(fields).add(field).build());
  }

  /**
   * Check whether this selector is a prefix of another selector.
   */
  public boolean isPrefixOf(FieldSelector sel) {
    for (int i = 0; i < fields.size(); i++) {
      if (i >= sel.fields.size() || fields.get(i) != sel.fields.get(i)) {
        return false;
      }
    }
    return true;
  }

  /**
   * Returns the HTTP parameter name of this selector. This is the sequence of proto field names
   * lower-cameled and joined by '.'.
   */
  public String getParamName() {
    if (paramName != null) {
      return paramName;
    }
    return paramName = Joiner.on('.').join(FluentIterable.from(fields)
        .transform(new Function() {
          @Override public String apply(Field field) {
            return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, field.getSimpleName());
          }
        }));
  }

  @Override public String toString() {
    return FIELD_PATH_JOINER.join(FluentIterable.from(fields).transform(
        new Function() {
          @Override public String apply(Field field) {
            return field.getSimpleName();
          }
        }));
  }

  @Override
  public int hashCode() {
    // Note that paramName doesn't count because it is derived.
    return Objects.hash(fields);
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
      return false;
    }
    FieldSelector other = (FieldSelector) obj;
    return Objects.equals(fields, other.fields);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy