Java tutorial
/* * Copyright 2016 Axibase Corporation or its affiliates. All Rights Reserved. * * 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 located at * * https://www.axibase.com/atsd/axibase-apache-2.0.pdf * * or in the "license" file accompanying this file. This file 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.axibase.tsd.driver.jdbc.content; import java.io.IOException; import java.net.MalformedURLException; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; import com.axibase.tsd.driver.jdbc.enums.AtsdType; import com.axibase.tsd.driver.jdbc.ext.AtsdException; import com.axibase.tsd.driver.jdbc.logging.LoggingFacade; import com.axibase.tsd.driver.jdbc.util.EnumUtil; import com.axibase.tsd.driver.jdbc.util.JsonMappingUtil; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import org.apache.calcite.avatica.AvaticaParameter; import org.apache.calcite.avatica.ColumnMetaData; import org.apache.calcite.avatica.Meta.CursorFactory; import org.apache.calcite.avatica.Meta.MetaResultSet; import org.apache.calcite.avatica.Meta.Signature; import org.apache.calcite.avatica.Meta.StatementType; import org.apache.commons.lang3.StringUtils; import static com.axibase.tsd.driver.jdbc.DriverConstants.*; @SuppressWarnings("unchecked") public class ContentMetadata { private static final LoggingFacade logger = LoggingFacade.getLogger(ContentMetadata.class); private final Signature sign; private final List<MetaResultSet> list; private final List<ColumnMetaData> metadataList; public ContentMetadata(String scheme, String sql, String connectionId, int statementId) throws AtsdException, IOException { metadataList = StringUtils.isNoneEmpty(scheme) ? buildMetadataList(scheme) : Collections.<ColumnMetaData>emptyList(); sign = new Signature(metadataList, sql, Collections.<AvaticaParameter>emptyList(), null, CursorFactory.LIST, StatementType.SELECT); list = Collections.unmodifiableList( Collections.singletonList(MetaResultSet.create(connectionId, statementId, false, sign, null))); } public Signature getSign() { return sign; } public List<MetaResultSet> getList() { return list; } public List<ColumnMetaData> getMetadataList() { return metadataList; } static List<ColumnMetaData> buildMetadataList(String json) throws JsonParseException, MalformedURLException, IOException, AtsdException { final Map<String, Object> jsonObject = getJsonScheme(json); if (jsonObject == null) { throw new AtsdException("Wrong metadata content"); } final Map<String, Object> publisher = (Map<String, Object>) jsonObject.get(PUBLISHER_SECTION); if (publisher == null) { throw new AtsdException("Wrong metadata publisher"); } final String schema = (String) publisher.get(SCHEMA_NAME_PROPERTY); if (schema == null) { throw new AtsdException("Wrong metadata schema"); } final Map<String, Object> tableSchema = (Map<String, Object>) jsonObject.get(TABLE_SCHEMA_SECTION); if (tableSchema == null) { throw new AtsdException("Wrong table schema"); } final List<Object> columns = (List<Object>) tableSchema.get(COLUMNS_SCHEME); if (columns == null) { throw new AtsdException("Wrong columns schema"); } final int size = columns.size(); ColumnMetaData[] sortedByOrdinal = new ColumnMetaData[size]; int index = 0; for (final Object obj : columns) { final ColumnMetaData cmd = getColumnMetaData(schema, index, obj); sortedByOrdinal[cmd.ordinal] = cmd; ++index; } if (logger.isDebugEnabled()) { logger.debug(String.format("Schema is processed. %s headers are found.", size)); } return Collections.unmodifiableList(Arrays.asList(sortedByOrdinal)); } private static ColumnMetaData getColumnMetaData(String schema, int ind, final Object obj) { final Map<String, Object> property = (Map<String, Object>) obj; final Integer index = (Integer) property.get(INDEX_PROPERTY); final int columnIndex = index != null ? index - 1 : ind; final String name = (String) property.get(NAME_PROPERTY); final String title = (String) property.get(TITLE_PROPERTY); final String table = (String) property.get(TABLE_PROPERTY); final String datatype = property.get(DATATYPE_PROPERTY).toString(); // may be represented as a json object (hashmap) final String propertyUrl = (String) property.get(PROPERTY_URL); final AtsdType atsdType = EnumUtil.getAtsdTypeByOriginalName(datatype); final int nullable = StringUtils.endsWithIgnoreCase(propertyUrl, "Tag") ? 1 : 0; return new ColumnMetaDataBuilder().withColumnIndex(columnIndex).withSchema(schema).withTable(table) .withName(name).withTitle(title).withAtsdType(atsdType).withNullable(nullable).build(); } private static Map<String, Object> getJsonScheme(String json) throws IOException { try (final JsonParser parser = JsonMappingUtil.getParser(json)) { final JsonToken token = parser.nextToken(); Class<?> type; if (token == JsonToken.START_OBJECT) { type = Map.class; } else if (token == JsonToken.START_ARRAY) { type = List.class; } else { type = String.class; } return (Map<String, Object>) parser.readValueAs(type); } } public static ColumnMetaData.AvaticaType getAvaticaType(AtsdType type) { return new ColumnMetaData.AvaticaType(type.sqlTypeCode, type.sqlType, type.avaticaType); } public static class ColumnMetaDataBuilder { private String name; private String title; private String table; private AtsdType atsdType; private int columnIndex; private int nullable; private String schema; public ColumnMetaDataBuilder withName(String name) { this.name = name; return this; } public ColumnMetaDataBuilder withTitle(String title) { this.title = title; return this; } public ColumnMetaDataBuilder withTable(String table) { this.table = table; return this; } public ColumnMetaDataBuilder withAtsdType(AtsdType atsdType) { this.atsdType = atsdType; return this; } public ColumnMetaDataBuilder withColumnIndex(int columnIndex) { this.columnIndex = columnIndex; return this; } public ColumnMetaDataBuilder withSchema(String schema) { this.schema = schema; return this; } public ColumnMetaDataBuilder withNullable(int nullable) { this.nullable = nullable; return this; } public ColumnMetaData build() { final ColumnMetaData.AvaticaType atype = getAvaticaType(atsdType); return new ColumnMetaData(columnIndex, false, false, false, false, nullable, false, atsdType.size, name, title, schema, 1, 1, table, DEFAULT_CATALOG_NAME, atype, true, false, false, atype.rep.clazz.getCanonicalName()); } } }