Package com.goodow.realtime.store.impl

Source Code of com.goodow.realtime.store.impl.CollaborativeMapImpl

/*
* Copyright 2012 Goodow.com
*
* 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.goodow.realtime.store.impl;

import com.goodow.realtime.core.Handler;
import com.goodow.realtime.core.Registration;
import com.goodow.realtime.json.Json;
import com.goodow.realtime.json.JsonArray;
import com.goodow.realtime.json.JsonObject;
import com.goodow.realtime.json.JsonObject.MapIterator;
import com.goodow.realtime.operation.Operation;
import com.goodow.realtime.operation.OperationComponent;
import com.goodow.realtime.operation.create.CreateComponent;
import com.goodow.realtime.operation.map.MapTarget;
import com.goodow.realtime.operation.map.json.JsonMapComponent;
import com.goodow.realtime.store.CollaborativeMap;
import com.goodow.realtime.store.CollaborativeObject;
import com.goodow.realtime.store.EventType;
import com.goodow.realtime.store.ValueChangedEvent;

class CollaborativeMapImpl extends CollaborativeObjectImpl implements CollaborativeMap {
  private final JsonObject snapshot;

  CollaborativeMapImpl(ModelImpl model) {
    super(model);
    snapshot = Json.createObject();
  }

  @Override public Registration onValueChanged(Handler<ValueChangedEvent> handler) {
    return addEventListener(EventType.VALUE_CHANGED, handler, false);
  }

  @Override public void clear() {
    model.beginCompoundOperation("map.clear");
    keys().forEach(new JsonArray.ListIterator<String>() {
      @Override
      public void call(int index, String key) {
        remove(key);
      }
    });
    model.endCompoundOperation();
  }

  @Override@SuppressWarnings("unchecked")
  public <T> T get(String key) {
    checkKey(key);
    return (T) JsonSerializer.deserializeObject(snapshot.getArray(key), model.objects);
  }

  @Override public boolean has(String key) {
    checkKey(key);
    return snapshot.has(key);
  }

  @Override public boolean isEmpty() {
    return size() == 0;
  }

  @Override
  public JsonArray items() {
    final JsonArray items = Json.createArray();
    snapshot.forEach(new MapIterator<JsonArray>() {
      @Override
      public void call(String key, JsonArray value) {
        JsonArray item = Json.createArray().push(key).push(get(key));
        items.push(item);
      }
    });
    return items;
  }

  @Override public JsonArray keys() {
    return snapshot.keys();
  }

  @Override
  public <T> T remove(String key) {
    checkKey(key);
    T oldValue = this.<T> get(key);
    if (oldValue == null) {
      return null;
    }
    JsonMapComponent op = new JsonMapComponent(id, key, snapshot.getArray(key), null);
    consumeAndSubmit(op);
    return oldValue;
  }

  @Override
  public <T> T set(String key, Object value) {
    checkKey(key);
    JsonArray serializedValue = JsonSerializer.serializeObject(value);
    T oldObject = this.<T> get(key);
    JsonArray oldValue = snapshot.getArray(key);
    if (!JsonMapComponent.jsonEquals(oldValue, serializedValue)) {
      JsonMapComponent op = new JsonMapComponent(id, key, oldValue, serializedValue);
      consumeAndSubmit(op);
    }
    return oldObject;
  }

  @Override public int size() {
    return snapshot.size();
  }

  @Override
  public JsonObject toJson() {
    final JsonObject json = Json.createObject();
    snapshot.forEach(new MapIterator<JsonArray>() {
      @Override
      public void call(String key, JsonArray value) {
        Object val = get(key);
        if (val instanceof CollaborativeObjectImpl) {
          json.set(key, ((CollaborativeObject) val).toJson());
        } else {
          json.set(key, snapshot.getArray(key).get(1));
        }
      }
    });
    return json;
  }

  @Override public JsonArray values() {
    final JsonArray values = Json.createArray();
    snapshot.forEach(new MapIterator<JsonArray>() {
      @Override
      public void call(String key, JsonArray value) {
        values.push(get(key));
      }
    });
    return values;
  }

  @SuppressWarnings("unchecked")
  @Override
  protected void consume(final String userId, final String sessionId,
      final OperationComponent<?> component) {
    ((Operation<MapTarget<JsonArray>>) component).apply(new MapTarget<JsonArray>() {
      @Override
      public void set(String key, JsonArray newValue) {
        if (newValue == null) {
          removeAndFireEvent(key, sessionId, userId);
          model.bytesUsed -= component.toString().length();
          model.bytesUsed -= 2;
        } else {
          putAndFireEvent(key, newValue, sessionId, userId);
        }
      }
    });
  }

  @Override
  OperationComponent<?>[] toInitialization() {
    final OperationComponent<?>[] toRtn = new OperationComponent[1 + size()];
    toRtn[0] = new CreateComponent(id, CreateComponent.MAP);
    if (!isEmpty()) {
      snapshot.forEach(new MapIterator<JsonArray>() {
        int i = 1;

        @Override
        public void call(String key, JsonArray value) {
          toRtn[i++] = new JsonMapComponent(id, key, null, snapshot.getArray(key));
        }
      });
    }
    return toRtn;
  }

  private void checkKey(String key) {
    if (key == null) {
      throw new IllegalArgumentException("Expected string for key, but was: null");
    }
  }

  private void putAndFireEvent(String key, JsonArray newValue, String sessionId, String userId) {
    assert null != newValue;
    Object newObject = JsonSerializer.deserializeObject(newValue, model.objects);
    ValueChangedEvent event =
        new ValueChangedEventImpl(event(sessionId, userId).set("property", key).set("oldValue",
            get(key)).set("newValue", newObject));
    if (snapshot.has(key)) {
      JsonArray oldValue = snapshot.getArray(key);
      model.addOrRemoveParent(oldValue, id, false);
      model.bytesUsed -= oldValue.toJsonString().length();
    }
    snapshot.set(key, newValue);
    model.addOrRemoveParent(newValue, id, true);
    fireEvent(event);
    model.bytesUsed += newValue.toJsonString().length();
  }

  private void removeAndFireEvent(String key, String sessionId, String userId) {
    assert has(key);
    JsonArray oldValue = snapshot.getArray(key);
    ValueChangedEvent event =
        new ValueChangedEventImpl(event(sessionId, userId).set("property", key).set("oldValue",
            get(key)).set("newValue", null));
    snapshot.remove(key);
    model.addOrRemoveParent(oldValue, id, false);
    fireEvent(event);
    model.bytesUsed -= oldValue.toJsonString().length();
  }
}
TOP

Related Classes of com.goodow.realtime.store.impl.CollaborativeMapImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.