/** * Copyright 2013-2014 Recruit Technologies Co., Ltd. and contributors * (see CONTRIBUTORS.md) * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. A copy of the * License is distributed with this work in the LICENSE.md file. You may * also obtain a copy of the License from * * 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.gennai.gungnir.tuple.schema; import static org.gennai.gungnir.GungnirConst.*; import java.util.Arrays; import java.util.List; import java.util.Map; import com.google.common.collect.Lists; import com.google.common.collect.Maps; public class TupleSchema extends BaseSchema { private static final long serialVersionUID = SERIAL_VERSION_UID; public static class FieldTypes { public static final PrimitiveType STRING = PrimitiveType.STRING; public static final PrimitiveType TINYINT = PrimitiveType.TINYINT; public static final PrimitiveType SMALLINT = PrimitiveType.SMALLINT; public static final PrimitiveType INT = PrimitiveType.INT; public static final PrimitiveType BIGINT = PrimitiveType.BIGINT; public static final PrimitiveType FLOAT = PrimitiveType.FLOAT; public static final PrimitiveType DOUBLE = PrimitiveType.DOUBLE; public static final PrimitiveType BOOLEAN = PrimitiveType.BOOLEAN; public static final TimestampType TIMESTAMP = new TimestampType(); // CHECKSTYLE IGNORE MethodName FOR NEXT 1 LINES public static TimestampType TIMESTAMP(String dateFormat) { return new TimestampType(dateFormat); } // CHECKSTYLE IGNORE MethodName FOR NEXT 1 LINES public static ListType LIST(FieldType elementType) { return new ListType(elementType); } // CHECKSTYLE IGNORE MethodName FOR NEXT 1 LINES public static MapType MAP(FieldType keyType, FieldType valueType) { return new MapType(keyType, valueType); } // CHECKSTYLE IGNORE MethodName FOR NEXT 1 LINES public static StructType STRUCT() { return new StructType(); } } private String tupleName; private List<String> fieldNames = Lists.newArrayList(); private List<FieldType> fieldTypes = Lists.newArrayList(); private String[] partitionFields; private transient Map<String, Integer> fieldsIndex; public TupleSchema(String tupleName) { super(); this.tupleName = tupleName; } private TupleSchema(TupleSchema c) { super(c); this.tupleName = c.tupleName; this.fieldNames = Lists.newArrayList(c.fieldNames); this.fieldTypes = Lists.newArrayList(c.fieldTypes); if (c.partitionFields != null) { this.partitionFields = Arrays.copyOf(c.partitionFields, c.partitionFields.length); } } @Override public String getSchemaName() { return tupleName; } @Override public int getFieldCount() { return fieldTypes.size(); } private void indexing() { if (fieldsIndex == null) { fieldsIndex = Maps.newHashMap(); for (int i = 0; i < fieldNames.size(); i++) { fieldsIndex.put(fieldNames.get(i), i); } } } @Override public Integer getFieldIndex(String fieldName) { indexing(); return fieldsIndex.get(fieldName); } @Override public String getFieldName(int index) { return fieldNames.get(index); } @Override public FieldType getFieldType(int index) { return fieldTypes.get(index); } @Override public List<String> getFieldNames() { return fieldNames; } @Override public String[] getPartitionFields() { return partitionFields; } public TupleSchema field(String fieldName, FieldType fieldType) { indexing(); if (fieldsIndex.containsKey(fieldName)) { fieldNames.set(fieldsIndex.get(fieldName), fieldName); fieldTypes.set(fieldsIndex.get(fieldName), fieldType); } else { Integer index = fieldTypes.size(); fieldsIndex.put(fieldName, index); fieldNames.add(fieldName); fieldTypes.add(fieldType); } return this; } public TupleSchema field(String fieldName) { return field(fieldName, null); } public TupleSchema partitioned(String... fieldNames) { partitionFields = fieldNames; return this; } @Override public void validate() throws SchemaValidateException { if (partitionFields != null) { for (String fieldName : partitionFields) { if (!fieldNames.contains(fieldName)) { throw new SchemaValidateException("'" + fieldName + "' field doesn't exist"); } } } } @Override public TupleSchema clone() { return new TupleSchema(this); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(tupleName); sb.append('('); for (int i = 0; i < fieldNames.size(); i++) { if (i > 0) { sb.append(", "); } sb.append(fieldNames.get(i)); if (fieldTypes.get(i) != null) { sb.append(' '); sb.append(fieldTypes.get(i)); } } sb.append(')'); if (partitionFields != null) { sb.append(" partitioned by "); for (int i = 0; i < partitionFields.length; i++) { if (i > 0) { sb.append(", "); } sb.append(partitionFields[i]); } } return sb.toString(); } }