org.curioswitch.common.testing.assertj.proto.FieldScopeUtil Maven / Gradle / Ivy
Show all versions of assertj-protobuf Show documentation
/*
* MIT License
*
* Copyright (c) 2018 Choko ([email protected])
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* 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 org.curioswitch.common.testing.assertj.proto;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.primitives.Ints;
import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Message;
import java.util.List;
/** Utility methods for {@link FieldScope}s and {@link FluentEqualityConfig}. */
final class FieldScopeUtil {
/**
* Returns a function which translates integer field numbers into field names using the Descriptor
* if available.
*
* @param fmt Format string that must contain exactly one '%s' and no other format parameters.
*/
static Function, String> fieldNumbersFunction(
final String fmt, final Iterable fieldNumbers) {
return new Function, String>() {
@Override
public String apply(Optional optDescriptor) {
return resolveFieldNumbers(optDescriptor, fmt, fieldNumbers);
}
};
}
/**
* Returns a function which formats the given string by getting the usingCorrespondenceString from
* the given FieldScope with the argument descriptor.
*
* @param fmt Format string that must contain exactly one '%s' and no other format parameters.
*/
static Function, String> fieldScopeFunction(
final String fmt, final FieldScope fieldScope) {
return new Function, String>() {
@Override
public String apply(Optional optDescriptor) {
return String.format(fmt, fieldScope.usingCorrespondenceString(optDescriptor));
}
};
}
/** Returns a function which concatenates the outputs of the two input functions. */
static Function, String> concat(
final Function super Optional, String> function1,
final Function super Optional, String> function2) {
return new Function, String>() {
@Override
public String apply(Optional optDescriptor) {
return function1.apply(optDescriptor) + function2.apply(optDescriptor);
}
};
}
/**
* Returns the singular descriptor used by all non-null messages in the list.
*
* If there is no descriptor, or more than one, returns {@code Optional.absent()}.
*/
static Optional getSingleDescriptor(Iterable extends Message> messages) {
Optional optDescriptor = Optional.absent();
for (Message message : messages) {
if (message != null) {
Descriptor descriptor = message.getDescriptorForType();
if (!optDescriptor.isPresent()) {
optDescriptor = Optional.of(descriptor);
} else if (descriptor != optDescriptor.get()) {
// Two different descriptors - abandon ship.
return Optional.absent();
}
}
}
return optDescriptor;
}
/** Joins the arguments into a {@link List} for convenience. */
static List asList(int first, int... rest) {
List list = Lists.newArrayList();
list.add(first);
list.addAll(Ints.asList(rest));
return list;
}
private static final Joiner JOINER = Joiner.on(", ");
static String join(Iterable> objects) {
return JOINER.join(objects);
}
/**
* Formats {@code fmt} with the field numbers, concatenated, if a descriptor is available to
* resolve them to field names. Otherwise it uses the raw integers.
*
* @param fmt Format string that must contain exactly one '%s' and no other format parameters.
*/
private static String resolveFieldNumbers(
Optional optDescriptor, String fmt, Iterable fieldNumbers) {
if (optDescriptor.isPresent()) {
Descriptor descriptor = optDescriptor.get();
List strings = Lists.newArrayList();
for (int fieldNumber : fieldNumbers) {
FieldDescriptor field = descriptor.findFieldByNumber(fieldNumber);
strings.add(field != null ? field.toString() : String.format("%d (?)", fieldNumber));
}
return String.format(fmt, join(strings));
} else {
return String.format(fmt, join(fieldNumbers));
}
}
private FieldScopeUtil() {}
}