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&lt;Type&gt;() {
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