001/* 002 * Copyright (C) 2012 Facebook, Inc. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may 005 * not use this file except in compliance with the License. You may obtain 006 * a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations 014 * under the License. 015 */ 016package com.facebook.swift.codec.metadata; 017 018import com.google.common.base.Function; 019import com.google.common.base.Optional; 020import com.google.common.collect.Collections2; 021import com.google.common.collect.ImmutableList; 022import com.google.common.collect.ImmutableSortedMap; 023import com.google.common.reflect.TypeToken; 024 025import javax.annotation.concurrent.Immutable; 026 027import java.lang.reflect.Type; 028import java.util.Collection; 029import java.util.List; 030import java.util.SortedMap; 031 032import static com.facebook.swift.codec.metadata.ThriftFieldMetadata.isTypePredicate; 033import static com.google.common.base.Preconditions.checkNotNull; 034import static com.google.common.collect.Maps.uniqueIndex; 035 036@Immutable 037public class ThriftStructMetadata 038{ 039 public static enum MetadataType { 040 STRUCT, UNION; 041 } 042 043 private final String structName; 044 045 private final MetadataType metadataType; 046 private final Optional<ThriftMethodInjection> builderMethod; 047 private final ImmutableList<String> documentation; 048 049 private final SortedMap<Short, ThriftFieldMetadata> fields; 050 051 private final Optional<ThriftConstructorInjection> constructorInjection; 052 053 private final List<ThriftMethodInjection> methodInjections; 054 private final Type structType; 055 private final Type builderType; 056 057 public ThriftStructMetadata( 058 String structName, 059 Type structType, 060 Type builderType, 061 MetadataType metadataType, 062 Optional<ThriftMethodInjection> builderMethod, 063 List<String> documentation, 064 List<ThriftFieldMetadata> fields, 065 Optional<ThriftConstructorInjection> constructorInjection, 066 List<ThriftMethodInjection> methodInjections) 067 { 068 this.builderType = builderType; 069 this.builderMethod = checkNotNull(builderMethod, "builderMethod is null"); 070 this.structName = checkNotNull(structName, "structName is null"); 071 this.metadataType = checkNotNull(metadataType, "metadataType is null"); 072 this.structType = checkNotNull(structType, "structType is null"); 073 this.constructorInjection = checkNotNull(constructorInjection, "constructorInjection is null"); 074 this.documentation = ImmutableList.copyOf(checkNotNull(documentation, "documentation is null")); 075 this.fields = ImmutableSortedMap.copyOf(uniqueIndex(checkNotNull(fields, "fields is null"), new Function<ThriftFieldMetadata, Short>() 076 { 077 @Override 078 public Short apply(ThriftFieldMetadata input) 079 { 080 return input.getId(); 081 } 082 })); 083 this.methodInjections = ImmutableList.copyOf(checkNotNull(methodInjections, "methodInjections is null")); 084 } 085 086 public String getStructName() 087 { 088 return structName; 089 } 090 091 public Type getStructType() 092 { 093 return structType; 094 } 095 096 public Class<?> getStructClass() 097 { 098 return TypeToken.of(structType).getRawType(); 099 } 100 101 public Type getBuilderType() 102 { 103 return builderType; 104 } 105 106 public Class<?> getBuilderClass() 107 { 108 return builderType == null ? null : TypeToken.of(builderType).getRawType(); 109 } 110 111 public MetadataType getMetadataType() 112 { 113 return metadataType; 114 } 115 116 public Optional<ThriftMethodInjection> getBuilderMethod() 117 { 118 return builderMethod; 119 } 120 121 public ThriftFieldMetadata getField(int id) 122 { 123 return fields.get((short) id); 124 } 125 126 public ImmutableList<String> getDocumentation() 127 { 128 return documentation; 129 } 130 131 public Collection<ThriftFieldMetadata> getFields(FieldKind type) 132 { 133 return Collections2.filter(getFields(), isTypePredicate(type)); 134 } 135 136 public Collection<ThriftFieldMetadata> getFields() 137 { 138 return fields.values(); 139 } 140 141 public Optional<ThriftConstructorInjection> getConstructorInjection() 142 { 143 return constructorInjection; 144 } 145 146 public List<ThriftMethodInjection> getMethodInjections() 147 { 148 return methodInjections; 149 } 150 151 public boolean isException() 152 { 153 return Exception.class.isAssignableFrom(getStructClass()); 154 } 155 156 public boolean isUnion() 157 { 158 return !isException() && getMetadataType() == MetadataType.UNION; 159 } 160 161 public boolean isStruct() 162 { 163 return !isException() && getMetadataType() == MetadataType.STRUCT; 164 } 165 166 @Override 167 public String toString() 168 { 169 final StringBuilder sb = new StringBuilder(); 170 sb.append("ThriftStructMetadata"); 171 sb.append("{structName='").append(structName).append('\''); 172 sb.append(", structType=").append(structType); 173 sb.append(", builderType=").append(builderType); 174 sb.append(", builderMethod=").append(builderMethod); 175 sb.append(", fields=").append(fields); 176 sb.append(", constructorInjection=").append(constructorInjection); 177 sb.append(", methodInjections=").append(methodInjections); 178 sb.append('}'); 179 return sb.toString(); 180 } 181}