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

org.jsimpledb.JMapFieldInfo Maven / Gradle / Ivy

There is a newer version: 3.6.1
Show newest version

/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package org.jsimpledb;

import com.google.common.base.Converter;
import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;

import java.util.List;
import java.util.NavigableMap;

import org.jsimpledb.change.MapFieldAdd;
import org.jsimpledb.change.MapFieldClear;
import org.jsimpledb.change.MapFieldRemove;
import org.jsimpledb.change.MapFieldReplace;
import org.jsimpledb.core.MapField;
import org.jsimpledb.core.ObjId;
import org.jsimpledb.core.Transaction;

class JMapFieldInfo extends JComplexFieldInfo {

    JMapFieldInfo(JMapField jfield) {
        super(jfield);
    }

    /**
     * Get the key sub-field info.
     */
    public JSimpleFieldInfo getKeyFieldInfo() {
        return this.getSubFieldInfos().get(0);
    }

    /**
     * Get the value sub-field info.
     */
    public JSimpleFieldInfo getValueFieldInfo() {
        return this.getSubFieldInfos().get(1);
    }

    @Override
    public String getSubFieldInfoName(JSimpleFieldInfo subFieldInfo) {
        if (subFieldInfo.getStorageId() == this.getKeyFieldInfo().getStorageId())
            return MapField.KEY_FIELD_NAME;
        if (subFieldInfo.getStorageId() == this.getValueFieldInfo().getStorageId())
            return MapField.VALUE_FIELD_NAME;
        throw new RuntimeException("internal error");
    }

    @Override
    public TypeToken getTypeToken(Class context) {
        return this.buildTypeToken(
          this.getKeyFieldInfo().getTypeToken(context).wrap(),
          this.getValueFieldInfo().getTypeToken(context).wrap());
    }

    // This method exists solely to bind the generic type parameters
    @SuppressWarnings("serial")
    private  TypeToken> buildTypeToken(TypeToken keyType, TypeToken valueType) {
        return new TypeToken>() { }
          .where(new TypeParameter() { }, keyType)
          .where(new TypeParameter() { }, valueType);
    }

    @Override
    void registerChangeListener(Transaction tx, int[] path, Iterable types, AllChangesListener listener) {
        tx.addMapFieldChangeListener(this.storageId, path, types, listener);
    }

    @Override
     void addChangeParameterTypes(List> types, Class targetType) {
        this.addChangeParameterTypes(types, targetType,
          this.getKeyFieldInfo().getTypeToken(targetType),
          this.getValueFieldInfo().getTypeToken(targetType));
    }

    // This method exists solely to bind the generic type parameters
    @SuppressWarnings("serial")
    private  void addChangeParameterTypes(List> types,
      Class targetType, TypeToken keyType, TypeToken valueType) {
        types.add(new TypeToken>() { }
          .where(new TypeParameter() { }, targetType)
          .where(new TypeParameter() { }, keyType.wrap())
          .where(new TypeParameter() { }, valueType.wrap()));
        types.add(new TypeToken>() { }
          .where(new TypeParameter() { }, targetType));
        types.add(new TypeToken>() { }
          .where(new TypeParameter() { }, targetType)
          .where(new TypeParameter() { }, keyType.wrap())
          .where(new TypeParameter() { }, valueType.wrap()));
        types.add(new TypeToken>() { }
          .where(new TypeParameter() { }, targetType)
          .where(new TypeParameter() { }, keyType.wrap())
          .where(new TypeParameter() { }, valueType.wrap()));
    }

    @Override
    public NavigableMapConverter getConverter(JTransaction jtx) {
        Converter keyConverter = this.getKeyFieldInfo().getConverter(jtx);
        Converter valueConverter = this.getValueFieldInfo().getConverter(jtx);
        if (keyConverter == null && valueConverter == null)
            return null;
        if (keyConverter == null)
           keyConverter = Converter.identity();
        if (valueConverter == null)
           valueConverter = Converter.identity();
        return this.createConverter(keyConverter, valueConverter);
    }

    // This method exists solely to bind the generic type parameters
    private  NavigableMapConverter createConverter(
      Converter keyConverter, Converter valueConverter) {
        return new NavigableMapConverter(keyConverter, valueConverter);
    }

    @Override
    public void copyRecurse(CopyState copyState, JTransaction srcTx, JTransaction dstTx,
      ObjId id, int storageId, int fieldIndex, int[] fields) {
        final NavigableMap map = srcTx.tx.readMapField(id, this.storageId, false);
        if (storageId == this.getKeyFieldInfo().getStorageId())
            this.copyRecurse(copyState, srcTx, dstTx, map.keySet(), fieldIndex, fields);
        else if (storageId == this.getValueFieldInfo().getStorageId())
            this.copyRecurse(copyState, srcTx, dstTx, map.values(), fieldIndex, fields);
        else
            throw new RuntimeException("internal error");
    }

// Object

    @Override
    public boolean equals(Object obj) {
        if (obj == this)
            return true;
        if (!super.equals(obj))
            return false;
        final JMapFieldInfo that = (JMapFieldInfo)obj;
        return this.getKeyFieldInfo().equals(that.getKeyFieldInfo()) && this.getValueFieldInfo().equals(that.getValueFieldInfo());
    }

    @Override
    public int hashCode() {
        return super.hashCode() ^ this.getKeyFieldInfo().hashCode() ^ this.getValueFieldInfo().hashCode();
    }
}