1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 <@pp.dropOutputFile /> 19 <@pp.changeOutputFile name="/org/apache/arrow/vector/types/pojo/ArrowType.java" /> 20 <#include "/@includes/license.ftl" /> 21 22 package org.apache.arrow.vector.types.pojo; 23 24 import com.google.flatbuffers.FlatBufferBuilder; 25 26 import java.util.Objects; 27 28 import org.apache.arrow.flatbuf.Type; 29 import org.apache.arrow.memory.BufferAllocator; 30 import org.apache.arrow.vector.types.*; 31 import org.apache.arrow.vector.FieldVector; 32 33 import com.fasterxml.jackson.annotation.JsonCreator; 34 import com.fasterxml.jackson.annotation.JsonIgnore; 35 import com.fasterxml.jackson.annotation.JsonProperty; 36 import com.fasterxml.jackson.annotation.JsonSubTypes; 37 import com.fasterxml.jackson.annotation.JsonTypeInfo; 38 39 /** 40 * Arrow types 41 * Source code generated using FreeMarker template ${.template_name} 42 **/ 43 @JsonTypeInfo( 44 use = JsonTypeInfo.Id.NAME, 45 include = JsonTypeInfo.As.PROPERTY, 46 property = "name") 47 @JsonSubTypes({ 48 <#list arrowTypes.types as type> 49 @JsonSubTypes.Type(value = ArrowType.${type.name?remove_ending("_")}.class, name = "${type.name?remove_ending("_")?lower_case}"), 50 </#list> 51 }) 52 public abstract class ArrowType { 53 54 public static abstract class PrimitiveType extends ArrowType { 55 PrimitiveType()56 private PrimitiveType() { 57 } 58 59 @Override isComplex()60 public boolean isComplex() { 61 return false; 62 } 63 } 64 65 public static abstract class ComplexType extends ArrowType { 66 ComplexType()67 private ComplexType() { 68 } 69 70 @Override isComplex()71 public boolean isComplex() { 72 return true; 73 } 74 } 75 76 public static enum ArrowTypeID { 77 <#list arrowTypes.types as type> 78 <#assign name = type.name> 79 ${name?remove_ending("_")}(Type.${name}), 80 </#list> 81 NONE(Type.NONE); 82 83 private final byte flatbufType; 84 getFlatbufID()85 public byte getFlatbufID() { 86 return this.flatbufType; 87 } 88 ArrowTypeID(byte flatbufType)89 private ArrowTypeID(byte flatbufType) { 90 this.flatbufType = flatbufType; 91 } 92 } 93 94 @JsonIgnore getTypeID()95 public abstract ArrowTypeID getTypeID(); 96 @JsonIgnore isComplex()97 public abstract boolean isComplex(); getType(FlatBufferBuilder builder)98 public abstract int getType(FlatBufferBuilder builder); accept(ArrowTypeVisitor<T> visitor)99 public abstract <T> T accept(ArrowTypeVisitor<T> visitor); 100 101 /** 102 * to visit the ArrowTypes 103 * <code> 104 * type.accept(new ArrowTypeVisitor<Type>() { 105 * ... 106 * }); 107 * </code> 108 */ 109 public static interface ArrowTypeVisitor<T> { 110 <#list arrowTypes.types as type> 111 T visit(${type.name?remove_ending("_")} type); 112 </#list> visit(ExtensionType type)113 default T visit(ExtensionType type) { 114 return type.storageType().accept(this); 115 } 116 } 117 118 /** 119 * to visit the Complex ArrowTypes and bundle Primitive ones in one case 120 */ 121 public static abstract class ComplexTypeVisitor<T> implements ArrowTypeVisitor<T> { 122 visit(PrimitiveType type)123 public T visit(PrimitiveType type) { 124 throw new UnsupportedOperationException("Unexpected Primitive type: " + type); 125 } 126 127 <#list arrowTypes.types as type> 128 <#if !type.complex> 129 public final T visit(${type.name?remove_ending("_")} type) { 130 return visit((PrimitiveType) type); 131 } 132 </#if> 133 </#list> 134 } 135 136 /** 137 * to visit the Primitive ArrowTypes and bundle Complex ones under one case 138 */ 139 public static abstract class PrimitiveTypeVisitor<T> implements ArrowTypeVisitor<T> { 140 visit(ComplexType type)141 public T visit(ComplexType type) { 142 throw new UnsupportedOperationException("Unexpected Complex type: " + type); 143 } 144 145 <#list arrowTypes.types as type> 146 <#if type.complex> 147 public final T visit(${type.name?remove_ending("_")} type) { 148 return visit((ComplexType) type); 149 } 150 </#if> 151 </#list> 152 } 153 154 <#list arrowTypes.types as type> 155 <#assign name = type.name?remove_ending("_")> 156 <#assign fields = type.fields> 157 public static class ${name} extends <#if type.complex>ComplexType<#else>PrimitiveType</#if> { 158 public static final ArrowTypeID TYPE_TYPE = ArrowTypeID.${name}; 159 <#if type.fields?size == 0> 160 public static final ${name} INSTANCE = new ${name}(); 161 <#else> 162 163 <#list fields as field> 164 <#assign fieldType = field.valueType!field.type> 165 ${fieldType} ${field.name}; 166 </#list> 167 168 @JsonCreator 169 public ${type.name}( 170 <#list type.fields as field> 171 <#assign fieldType = field.valueType!field.type> 172 @JsonProperty("${field.name}") ${fieldType} ${field.name}<#if field_has_next>, </#if> 173 </#list> 174 ) { 175 <#list type.fields as field> 176 this.${field.name} = ${field.name}; 177 </#list> 178 } 179 180 <#list fields as field> 181 <#assign fieldType = field.valueType!field.type> 182 public ${fieldType} get${field.name?cap_first}() { 183 return ${field.name}; 184 } 185 </#list> 186 </#if> 187 188 @Override getTypeID()189 public ArrowTypeID getTypeID() { 190 return TYPE_TYPE; 191 } 192 193 @Override getType(FlatBufferBuilder builder)194 public int getType(FlatBufferBuilder builder) { 195 <#list type.fields as field> 196 <#if field.type == "String"> 197 int ${field.name} = this.${field.name} == null ? -1 : builder.createString(this.${field.name}); 198 </#if> 199 <#if field.type == "int[]"> 200 int ${field.name} = this.${field.name} == null ? -1 : org.apache.arrow.flatbuf.${type.name}.create${field.name?cap_first}Vector(builder, this.${field.name}); 201 </#if> 202 </#list> 203 org.apache.arrow.flatbuf.${type.name}.start${type.name}(builder); 204 <#list type.fields as field> 205 <#if field.type == "String" || field.type == "int[]"> 206 if (this.${field.name} != null) { 207 org.apache.arrow.flatbuf.${type.name}.add${field.name?cap_first}(builder, ${field.name}); 208 } 209 <#else> 210 org.apache.arrow.flatbuf.${type.name}.add${field.name?cap_first}(builder, this.${field.name}<#if field.valueType??>.getFlatbufID()</#if>); 211 </#if> 212 </#list> 213 return org.apache.arrow.flatbuf.${type.name}.end${type.name}(builder); 214 } 215 216 public String toString() { 217 return "${name}" 218 <#if fields?size != 0> 219 + "(" 220 <#list fields as field> 221 + <#if field.type == "int[]">java.util.Arrays.toString(${field.name})<#else>${field.name}</#if><#if field_has_next> + ", " </#if> 222 </#list> 223 + ")" 224 </#if> 225 ; 226 } 227 228 @Override 229 public int hashCode() { 230 return java.util.Arrays.deepHashCode(new Object[] {<#list type.fields as field>${field.name}<#if field_has_next>, </#if></#list>}); 231 } 232 233 @Override 234 public boolean equals(Object obj) { 235 if (!(obj instanceof ${name})) { 236 return false; 237 } 238 <#if type.fields?size == 0> 239 return true; 240 <#else> 241 ${type.name} that = (${type.name}) obj; 242 return <#list type.fields as field>Objects.deepEquals(this.${field.name}, that.${field.name}) <#if field_has_next>&&<#else>;</#if> 243 </#list> 244 </#if> 245 } 246 247 @Override 248 public <T> T accept(ArrowTypeVisitor<T> visitor) { 249 return visitor.visit(this); 250 } 251 } 252 </#list> 253 254 /** 255 * A user-defined data type that wraps an underlying storage type. 256 */ 257 public abstract static class ExtensionType extends ComplexType { 258 /** The on-wire type for this user-defined type. */ 259 public abstract ArrowType storageType(); 260 /** The name of this user-defined type. Used to identify the type during serialization. */ 261 public abstract String extensionName(); 262 /** Check equality of this type to another user-defined type. */ 263 public abstract boolean extensionEquals(ExtensionType other); 264 /** Save any metadata for this type. */ 265 public abstract String serialize(); 266 /** Given saved metadata and the underlying storage type, construct a new instance of the user type. */ 267 public abstract ArrowType deserialize(ArrowType storageType, String serializedData); 268 /** Construct a vector for the user type. */ 269 public abstract FieldVector getNewVector(String name, FieldType fieldType, BufferAllocator allocator); 270 271 /** The field metadata key storing the name of the extension type. */ 272 public static final String EXTENSION_METADATA_KEY_NAME = "ARROW:extension:name"; 273 /** The field metadata key storing metadata for the extension type. */ 274 public static final String EXTENSION_METADATA_KEY_METADATA = "ARROW:extension:metadata"; 275 276 @Override 277 public ArrowTypeID getTypeID() { 278 return storageType().getTypeID(); 279 } 280 281 @Override 282 public int getType(FlatBufferBuilder builder) { 283 return storageType().getType(builder); 284 } 285 286 public String toString() { 287 return "ExtensionType(" + extensionName() + ", " + storageType().toString() + ")"; 288 } 289 290 @Override 291 public int hashCode() { 292 return java.util.Arrays.deepHashCode(new Object[] {storageType(), extensionName()}); 293 } 294 295 @Override 296 public boolean equals(Object obj) { 297 if (!(obj instanceof ExtensionType)) { 298 return false; 299 } 300 return this.extensionEquals((ExtensionType) obj); 301 } 302 303 @Override 304 public <T> T accept(ArrowTypeVisitor<T> visitor) { 305 return visitor.visit(this); 306 } 307 } 308 309 public static org.apache.arrow.vector.types.pojo.ArrowType getTypeForField(org.apache.arrow.flatbuf.Field field) { 310 switch(field.typeType()) { 311 <#list arrowTypes.types as type> 312 <#assign name = type.name?remove_ending("_")> 313 <#assign nameLower = type.name?lower_case> 314 <#assign fields = type.fields> 315 case Type.${type.name}: { 316 org.apache.arrow.flatbuf.${type.name} ${nameLower}Type = (org.apache.arrow.flatbuf.${type.name}) field.type(new org.apache.arrow.flatbuf.${type.name}()); 317 <#list type.fields as field> 318 <#if field.type == "int[]"> 319 ${field.type} ${field.name} = new int[${nameLower}Type.${field.name}Length()]; 320 for (int i = 0; i< ${field.name}.length; ++i) { 321 ${field.name}[i] = ${nameLower}Type.${field.name}(i); 322 } 323 <#else> 324 ${field.type} ${field.name} = ${nameLower}Type.${field.name}(); 325 </#if> 326 </#list> 327 return new ${name}(<#list type.fields as field><#if field.valueType??>${field.valueType}.fromFlatbufID(${field.name})<#else>${field.name}</#if><#if field_has_next>, </#if></#list>); 328 } 329 </#list> 330 default: 331 throw new UnsupportedOperationException("Unsupported type: " + field.typeType()); 332 } 333 } 334 335 public static Int getInt(org.apache.arrow.flatbuf.Field field) { 336 org.apache.arrow.flatbuf.Int intType = (org.apache.arrow.flatbuf.Int) field.type(new org.apache.arrow.flatbuf.Int()); 337 return new Int(intType.bitWidth(), intType.isSigned()); 338 } 339 } 340 341 342