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

com.getperka.flatpack.inject.PackScope Maven / Gradle / Ivy

There is a newer version: 2.21.0
Show newest version
/*
 * #%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.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 {
    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  Provider provider() {
    return cast(DummyProvider.INSTANCE);
  }

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

  /**
   * Retains the thread-local data.
   */
  private final ThreadLocal, Object>> allData = new ThreadLocal, Object>>();

  PackScope() {}

  public PackScope enter() {
    if (allData.get() != null) {
      throw new IllegalStateException("Already in a PackScope");
    }
    allData.set(FlatPackCollections., Object> mapForLookup());
    return this;
  }

  public void exit() {
    allData.remove();
  }

  @Override
  public  Provider scope(final Key key, final Provider unscoped) {
    return cast(new Provider() {
      @Override
      public Object get() {
        Map, Object> map = allData.get();
        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 key = Key.get(JsonWriter.class);
    if (writer == null) {
      allData.get().remove(key);
    } else {
      allData.get().put(key, writer);
    }
    return this;
  }

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

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

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