All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.linkedin.restli.common.KeyValueRecordFactory Maven / Gradle / Ivy

Go to download

Pegasus is a framework for building robust, scalable service architectures using dynamic discovery and simple asychronous type-checked REST + JSON APIs.

There is a newer version: 27.7.18
Show newest version
/*
   Copyright (c) 2013 LinkedIn Corp.

   Licensed 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.linkedin.restli.common;


import com.linkedin.data.schema.DataSchema;
import com.linkedin.data.schema.RecordDataSchema;
import com.linkedin.data.template.DataTemplateUtil;
import com.linkedin.data.template.RecordTemplate;
import java.util.Map;


/**
 *
 * @author kparikh
 */
public class KeyValueRecordFactory
{
  // A CompoundKey is being stored as a DataMap in the KeyValueRecord.
  private static final String COMPOUND_KEY_SCHEMA_STRING = "{\n" +
      "  \"type\": \"record\",\n" +
      "  \"name\": \"CompoundKeySchema\",\n" +
      "  \"namespace\": \"com.linkedin.restli.common\",\n" +
      "  \"fields\": []\n" +
      "}";
  static final DataSchema COMPOUND_KEY_SCHEMA = DataTemplateUtil.parseSchema(COMPOUND_KEY_SCHEMA_STRING);

  private final TypeSpec _keyType;
  private final ComplexKeySpec _complexKeyType;
  private final Map _fieldTypes;
  private final TypeSpec _valueType;

  private final ResourceKeyType _resourceKeyType;

  RecordDataSchema.Field _keyField;
  RecordDataSchema.Field _paramsField;
  RecordDataSchema.Field _valueField;

  public KeyValueRecordFactory(final Class keyClass,
                               final Class keyKeyClass,
                               final Class keyParamsClass,
                               final Map fieldTypes,
                               final Class valueClass)
  {
    this(TypeSpec.forClassMaybeNull(keyClass),
         ComplexKeySpec.forClassesMaybeNull(keyKeyClass, keyParamsClass),
         fieldTypes,
         TypeSpec.forClassMaybeNull(valueClass));
  }

  public KeyValueRecordFactory(final TypeSpec keyType,
                               final ComplexKeySpec complexKeyType,
                               final Map fieldTypes,
                               final TypeSpec valueType)
  {
    _keyType = keyType;
    _complexKeyType = complexKeyType;
    _valueType = valueType;
    _fieldTypes = fieldTypes;
    _resourceKeyType = getResourceKeyType(_keyType.getType());

    StringBuilder sb = new StringBuilder(10);

    switch (_resourceKeyType)
    {
      case PRIMITIVE:
        _keyField = new RecordDataSchema.Field(_keyType.getSchema());
        _keyField.setName(KeyValueRecord.KEY_FIELD_NAME, sb);
        break;
      case COMPLEX:
        _keyField = new RecordDataSchema.Field(_complexKeyType.getKeyType().getSchema());
        _keyField.setName(KeyValueRecord.KEY_FIELD_NAME, sb);
        _paramsField = new RecordDataSchema.Field(_complexKeyType.getParamsType().getSchema());
        _paramsField.setName(KeyValueRecord.PARAMS_FIELD_NAME, sb);
        break;
      case COMPOUND:
        if (_fieldTypes == null)
        {
          throw new IllegalArgumentException("Must specify field types for a CompoundKey!");
        }
        _keyField = new RecordDataSchema.Field(COMPOUND_KEY_SCHEMA);
        _keyField.setName(KeyValueRecord.KEY_FIELD_NAME, sb);
        break;
    }

    _valueField = new RecordDataSchema.Field(_valueType.getSchema());
    _valueField.setName(KeyValueRecord.VALUE_FIELD_NAME, sb);
  }

  private ResourceKeyType getResourceKeyType(Class type)
  {
    if (CompoundKey.class.isAssignableFrom(type))
    {
      return ResourceKeyType.COMPOUND;
    }
    else if (type.equals(ComplexResourceKey.class))
    {
      return ResourceKeyType.COMPLEX;
    }
    else
    {
      return ResourceKeyType.PRIMITIVE;
    }
  }

  /**
   * Build a {@link KeyValueRecord}
   * @param key the key to be stored
   * @param value the value to be stored
   * @return a {@link KeyValueRecord} with the key {@code key} and value {@code value}
   */
  public KeyValueRecord create(final K key, final V value)
  {
    final KeyValueRecord keyValueRecord = new KeyValueRecord();

    switch (_resourceKeyType)
    {
      case PRIMITIVE:
        keyValueRecord.setPrimitiveKey(_keyField, key, _keyType);
        break;
      case COMPLEX:
        keyValueRecord.setComplexKey(_keyField, _paramsField, key, _complexKeyType);
        break;
      case COMPOUND:
        keyValueRecord.setCompoundKey(_keyField, key, _fieldTypes);
        break;
    }

    keyValueRecord.setValue(_valueField, value, _valueType.getType());

    return keyValueRecord;
  }

  private static enum ResourceKeyType
  {
    PRIMITIVE,
    COMPLEX,
    COMPOUND
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy