![JAR search and dependency download from the Maven repository](/logo.png)
com.facebook.swift.service.metadata.ThriftServiceMetadata Maven / Gradle / Ivy
/*
* Copyright (C) 2012 Facebook, 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.facebook.swift.service.metadata;
import com.facebook.swift.codec.metadata.ThriftCatalog;
import com.facebook.swift.service.ThriftMethod;
import com.facebook.swift.service.ThriftService;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.*;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import java.lang.reflect.Method;
import java.util.*;
import static com.facebook.swift.codec.metadata.ReflectionHelper.findAnnotatedMethods;
import static com.facebook.swift.codec.metadata.ReflectionHelper.getEffectiveClassAnnotations;
@Immutable
public class ThriftServiceMetadata
{
private final String name;
private final Map methods;
private final Map declaredMethods;
private final ImmutableList parentServices;
private final ImmutableList documentation;
public ThriftServiceMetadata(Class> serviceClass, ThriftCatalog catalog)
{
Preconditions.checkNotNull(serviceClass, "serviceClass is null");
ThriftService thriftService = getThriftServiceAnnotation(serviceClass);
if (thriftService.value().length() == 0) {
name = serviceClass.getSimpleName();
}
else {
name = thriftService.value();
}
documentation = ThriftCatalog.getThriftDocumentation(serviceClass);
ImmutableMap.Builder builder = ImmutableMap.builder();
Function methodMetadataNamer = new Function() {
@Nullable
@Override
public String apply(@Nullable ThriftMethodMetadata methodMetadata)
{
return methodMetadata.getName();
}
};
// A multimap from order to method name. Sorted by key (order), with nulls (i.e. no order) last.
// Within each key, values (ThriftMethodMetadata) are sorted by method name.
TreeMultimap declaredMethods = TreeMultimap.create(
Ordering.natural().nullsLast(),
Ordering.natural().onResultOf(methodMetadataNamer));
for (Method method : findAnnotatedMethods(serviceClass, ThriftMethod.class)) {
if (method.isAnnotationPresent(ThriftMethod.class)) {
ThriftMethodMetadata methodMetadata = new ThriftMethodMetadata(name, method, catalog);
builder.put(methodMetadata.getName(), methodMetadata);
if (method.getDeclaringClass().equals(serviceClass)) {
declaredMethods.put(ThriftCatalog.getMethodOrder(method), methodMetadata);
}
}
}
methods = builder.build();
// create a name->metadata map keeping the order
this.declaredMethods = Maps.uniqueIndex(declaredMethods.values(), methodMetadataNamer);
ThriftServiceMetadata parentService = null;
ImmutableList.Builder parentServiceBuilder = ImmutableList.builder();
for (Class> parent : serviceClass.getInterfaces()) {
if (!getEffectiveClassAnnotations(parent, ThriftService.class).isEmpty()) {
parentServiceBuilder.add(new ThriftServiceMetadata(parent, catalog));
}
}
this.parentServices = parentServiceBuilder.build();
}
public ThriftServiceMetadata(String name, ThriftMethodMetadata... methods)
{
this.name = name;
ImmutableMap.Builder builder = ImmutableMap.builder();
for (ThriftMethodMetadata method : methods) {
builder.put(method.getName(), method);
}
this.methods = builder.build();
this.declaredMethods = this.methods;
this.parentServices = ImmutableList.of();
this.documentation = ImmutableList.of();
}
public String getName()
{
return name;
}
public ThriftMethodMetadata getMethod(String name)
{
return methods.get(name);
}
public Map getMethods()
{
return methods;
}
public Map getDeclaredMethods()
{
return declaredMethods;
}
public ImmutableList getDocumentation()
{
return documentation;
}
public static ThriftService getThriftServiceAnnotation(Class> serviceClass)
{
Set serviceAnnotations = getEffectiveClassAnnotations(serviceClass, ThriftService.class);
Preconditions.checkArgument(!serviceAnnotations.isEmpty(), "Service class %s is not annotated with @ThriftService", serviceClass.getName());
Preconditions.checkArgument(serviceAnnotations.size() == 1,
"Service class %s has multiple conflicting @ThriftService annotations: %s",
serviceClass.getName(),
serviceAnnotations
);
return Iterables.getOnlyElement(serviceAnnotations);
}
public ImmutableList getParentServices()
{
return parentServices;
}
public ThriftServiceMetadata getParentService()
{
// Assert that we have 0 or 1 parent.
// Having multiple @ThriftService parents is generally supported by swift,
// but this is a restriction that applies to swift2thrift generator (because the Thrift IDL doesn't)
Preconditions.checkState(parentServices.size() <= 1);
if (parentServices.isEmpty()) {
return null;
} else {
return parentServices.get(0);
}
}
@Override
public int hashCode()
{
return Objects.hash(name, methods, parentServices);
}
@Override
public boolean equals(Object obj)
{
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
final ThriftServiceMetadata other = (ThriftServiceMetadata) obj;
return Objects.equals(this.name, other.name) && Objects.equals(this.methods, other.methods) && Objects.equals(this.parentServices, other.parentServices);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy