Package com.getperka.flatpack.inject

Source Code of com.getperka.flatpack.inject.PackScope

/*
* #%L
* FlatPack serialization code
* %%
* Copyright (C) 2012 Perka Inc.
* %%
* 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.
* #L%
*/
package com.getperka.flatpack.inject;

import java.security.Principal;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Map;

import org.joda.time.DateTime;

import com.getperka.flatpack.FlatPackEntity;
import com.getperka.flatpack.TraversalMode;
import com.getperka.flatpack.util.FlatPackCollections;
import com.google.gson.stream.JsonWriter;
import com.google.inject.Key;
import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
import com.google.inject.Scope;

/**
* Provides injection for objects whose lifespans are bounded by a pack or unpack operation.
*/
public class PackScope implements Scope {

  private static class DummyProvider implements Provider<Object> {
    private static final DummyProvider INSTANCE = new DummyProvider();

    @Override
    public Object get() {
      throw new IllegalStateException("Not in a PackScope");
    }
  }

  /**
   * Returns a dummy provider that always throws an exception. This provider is injected as the
   * default provider for bindings that can only be satisfied inside of the pack scope.
   */
  public static <T> Provider<T> provider() {
    return cast(DummyProvider.INSTANCE);
  }

  /**
   * Utility method for an unchecked cast.
   */
  @SuppressWarnings("unchecked")
  private static <T> Provider<T> cast(Provider<?> provider) {
    return (Provider<T>) provider;
  }

  /**
   * Retains the thread-local data.
   */
  private final ThreadLocal<Deque<Map<Key<?>, Object>>> allData = new ThreadLocal<Deque<Map<Key<?>, Object>>>() {

    @Override
    protected Deque<Map<Key<?>, Object>> initialValue() {
      return new ArrayDeque<Map<Key<?>, Object>>();
    }
  };

  PackScope() {}

  public PackScope enter() {
    allData.get().push(FlatPackCollections.<Key<?>, Object> mapForLookup());
    return this;
  }

  public void exit() {
    Deque<Map<Key<?>, Object>> deque = allData.get();
    if (!deque.isEmpty()) {
      deque.pop();
    }
  }

  public boolean isEntered() {
    return !allData.get().isEmpty();
  }

  @Override
  public <T> Provider<T> scope(final Key<T> key, final Provider<T> unscoped) {
    return cast(new Provider<Object>() {
      @Override
      public Object get() {
        Map<Key<?>, Object> map = data();
        if (map == null) {
          throw new OutOfScopeException("Not in a PackScope");
        }
        Object toReturn = map.get(key);
        if (toReturn == null) {
          toReturn = unscoped.get();
          map.put(key, toReturn);
        }
        return toReturn;
      }
    });
  }

  public PackScope withEntity(FlatPackEntity<?> entity) {
    withLastModifiedTime(entity.getLastModifiedTime());
    withPrincipal(entity.getPrincipal());
    withTraversalMode(entity.getTraversalMode());
    return this;
  }

  public PackScope withJsonWriter(JsonWriter writer) {
    Key<JsonWriter> key = Key.get(JsonWriter.class);
    if (writer == null) {
      data().remove(key);
    } else {
      data().put(key, writer);
    }
    return this;
  }

  public PackScope withLastModifiedTime(DateTime lastModified) {
    Key<DateTime> key = Key.get(DateTime.class, LastModifiedTime.class);
    if (lastModified == null) {
      lastModified = new DateTime(0);
    }
    data().put(key, lastModified);
    return this;
  }

  public PackScope withPrincipal(Principal principal) {
    Key<Principal> key = Key.get(Principal.class);
    if (principal == null) {
      data().remove(key);
    } else {
      data().put(key, principal);
    }
    return this;
  }

  public PackScope withTraversalMode(TraversalMode mode) {
    Key<TraversalMode> key = Key.get(TraversalMode.class);
    if (mode == null) {
      data().remove(key);
    } else {
      data().put(key, mode);
    }
    return this;
  }

  private Map<Key<?>, Object> data() {
    return allData.get().peek();
  }
}
TOP

Related Classes of com.getperka.flatpack.inject.PackScope

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.