com.ning.metrics.goodwill.access.GoodwillSchema.java Source code

Java tutorial

Introduction

Here is the source code for com.ning.metrics.goodwill.access.GoodwillSchema.java

Source

/*
 * Copyright 2010-2011 Ning, Inc.
 *
 * Ning licenses this file to you under the Apache License, version 2.0
 * (the "License"); you may not use this file except in compliance with the
 * License.  You may obtain a copy of the License at:
 *
 *    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 com.ning.metrics.goodwill.access;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;

/**
 * Describe a Schema in Goodwill.
 * This is basically a union of a Schema and extra metadata for the Sink.
 *
 * @see com.ning.metrics.serialization.schema.Schema
 */
public class GoodwillSchema {
    private static final ObjectMapper mapper = new ObjectMapper();

    private final String name;
    private String sinkAddInfo;
    private final HashMap<Short, GoodwillSchemaField> thriftItems = new HashMap<Short, GoodwillSchemaField>();

    public static final String JSON_THRIFT_TYPE_NAME = "name";
    public static final String JSON_THRIFT_TYPE_SCHEMA = "schema";
    public static final String JSON_THRIFT_TYPE_SINK_ADD_INFO = "sinkAddInfo";

    /**
     * Jackson constructor
     * <p/>
     * {
     * "sinkAddInfo": null,
     * "name": "hello",
     * "schema": [
     * {
     * "name": "my hello attribute",
     * "type": "string",
     * "position": 1,
     * "description": "awesome attribute",
     * "sql": {
     * "type": "nvarchar",
     * "length": null,
     * "scale": null,
     * "precision": null
     * }
     * },
     * {
     * "name": "dsfdfsfds",
     * "type": "bool",
     * "position": 2,
     * "description": "dfsfdsfds",
     * "sql": {
     * "type": "boolean",
     * "length": null,
     * "scale": null,
     * "precision": null
     * }
     * },
     * {
     * "name": "wer",
     * "type": "double",
     * "position": 3,
     * "description": "wer",
     * "sql": {
     * "type": "numeric",
     * "length": null,
     * "scale": 12,
     * "precision": 42
     * }
     * }
     * ]
     * }
     *
     * @param name        Schema name
     * @param items       List of fields
     * @param sinkAddInfo extra information for the Sink
     */
    @JsonCreator
    public GoodwillSchema(@JsonProperty(JSON_THRIFT_TYPE_NAME) final String name,
            @JsonProperty(JSON_THRIFT_TYPE_SCHEMA) final List<GoodwillSchemaField> items,
            @JsonProperty(JSON_THRIFT_TYPE_SINK_ADD_INFO) final String sinkAddInfo) {
        this(name, items);
        setSinkAddInfo(sinkAddInfo);
    }

    /**
     * Manual constructor, typically used by Goodwill stores.
     *
     * @param name  Schema name
     * @param items List of fields
     */
    public GoodwillSchema(final String name, final List<GoodwillSchemaField> items) {
        this.name = name;
        for (final GoodwillSchemaField field : items) {
            addThriftField(field);
        }
    }

    public static GoodwillSchema decode(final String thriftJson) throws IOException {
        return mapper.readValue(thriftJson, GoodwillSchema.class);
    }

    @JsonValue
    @SuppressWarnings({ "unchecked" })
    public ImmutableMap toMap() {
        return new ImmutableMap.Builder().put(JSON_THRIFT_TYPE_NAME, getName())
                .put(JSON_THRIFT_TYPE_SCHEMA, getSchema())
                .put(JSON_THRIFT_TYPE_SINK_ADD_INFO, sinkAddInfo == null ? "" : sinkAddInfo).build();
    }

    /**
     * Add a field in the Thrift. The code does not enforce sanity w.r.t. field positions.
     *
     * @param goodwillSchemaField field to add
     */
    public void addThriftField(final GoodwillSchemaField goodwillSchemaField) {
        thriftItems.put(goodwillSchemaField.getId(), goodwillSchemaField);
    }

    public String getName() {
        return name;
    }

    /**
     * Get the schema as a collection of fields.
     * We guarantee the ordering by field id.
     *
     * @return the sorted collection of fields
     */
    public ArrayList<GoodwillSchemaField> getSchema() {
        final ArrayList<GoodwillSchemaField> items = new ArrayList<GoodwillSchemaField>(thriftItems.values());

        Collections.sort(items, new Comparator<GoodwillSchemaField>() {
            @Override
            public int compare(final GoodwillSchemaField left, final GoodwillSchemaField right) {
                return Short.valueOf(left.getId()).compareTo(right.getId());
            }
        });

        return items;
    }

    public void setSinkAddInfo(final String sinkAddInfo) {
        this.sinkAddInfo = sinkAddInfo;
    }

    /**
     * Given a position, return the field at that position.
     *
     * @param i position in the Thrift (start with 1)
     * @return the GoodwillSchemaField object
     */
    public GoodwillSchemaField getFieldByPosition(final short i) {
        return thriftItems.get(i);
    }

    /**
     * Given a name, return the field matching the name.
     *
     * @param name GoodwillSchemaField name
     * @return the GoodwillSchemaField object
     */
    public GoodwillSchemaField getFieldByName(final String name) {
        for (final GoodwillSchemaField field : thriftItems.values()) {
            if (field.getName().equals(name)) {
                return field;
            }
        }

        return null;
    }

    @Override
    public String toString() {
        try {
            return mapper.writeValueAsString(this);
        } catch (JsonGenerationException e) {
            return "GoodwillSchema{" + JSON_THRIFT_TYPE_NAME + "='" + getName() + '\'' + ", thriftItems="
                    + getSchema() + '}';
        } catch (IOException e) {
            return "GoodwillSchema{" + JSON_THRIFT_TYPE_NAME + "='" + getName() + '\'' + ", thriftItems="
                    + getSchema() + '}';
        }
    }

    public byte[] toJSONBytes() throws IOException {
        return mapper.writeValueAsBytes(this);
    }

    /**
     * @deprecated Use 'toJSONBytes()' instead
     */
    @Deprecated
    public ByteArrayOutputStream toJSON() throws IOException {
        // silly, but 
        final byte[] bytes = toJSONBytes();
        final ByteArrayOutputStream out = new ByteArrayOutputStream(bytes.length);
        out.write(bytes);
        return out;
    }
}