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

org.smallmind.nutsnbolts.context.ContextFactory Maven / Gradle / Ivy

There is a newer version: 6.3.0
Show newest version
/*
 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 David Berkman
 * 
 * This file is part of the SmallMind Code Project.
 * 
 * The SmallMind Code Project is free software, you can redistribute
 * it and/or modify it under either, at your discretion...
 * 
 * 1) The terms of GNU Affero General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * ...or...
 * 
 * 2) The terms of the Apache License, Version 2.0.
 * 
 * The SmallMind Code Project is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License or Apache License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * and the Apache License along with the SmallMind Code Project. If not, see
 *  or .
 * 
 * Additional permission under the GNU Affero GPL version 3 section 7
 * ------------------------------------------------------------------
 * If you modify this Program, or any covered work, by linking or
 * combining it with other code, such other code is not for that reason
 * alone subject to any of the requirements of the GNU Affero GPL
 * version 3.
 */
package org.smallmind.nutsnbolts.context;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;

public class ContextFactory {

  private static final InheritableThreadLocal, ContextStack>> CONTEXT_MAP_LOCAL = new InheritableThreadLocal, ContextStack>>() {

    @Override
    protected Map, ContextStack> initialValue () {

      return new HashMap<>();
    }

    @Override
    protected Map, ContextStack> childValue (Map, ContextStack> parentValue) {

      return new HashMap<>(parentValue);
    }
  };

  public static  void importContextTrace (Class contextClass, Context... contexts) {

    ContextStack contextStack;

    if ((contexts != null) && (contexts.length > 0)) {

      if ((contextStack = CONTEXT_MAP_LOCAL.get().get(contextClass)) == null) {
        CONTEXT_MAP_LOCAL.get().put(contextClass, contextStack = new ContextStack());
      }

      for (Context context : contexts) {
        contextStack.push(contextClass.cast(context));
      }
    }
  }

  public static  C[] exportContextTrace (Class contextClass) {

    C[] contexts;
    C context;
    LinkedList contextList;
    ContextStack contextStack;

    contextList = new LinkedList<>();
    if ((contextStack = CONTEXT_MAP_LOCAL.get().get(contextClass)) != null) {
      while ((context = contextStack.pop()) != null) {
        contextList.addFirst(context);
      }
    }

    contexts = (C[])Array.newInstance(contextClass, contextList.size());
    contextList.toArray(contexts);

    return contexts;
  }

  public static  void clearContextTrace (Class contextClass) {

    C context;
    ContextStack contextStack;

    if ((contextStack = CONTEXT_MAP_LOCAL.get().get(contextClass)) != null) {
      do {
        context = contextStack.pop();
      } while (context != null);
    }
  }

  public static  boolean exists (Class contextClass) {

    ContextStack contextStack;

    return ((contextStack = CONTEXT_MAP_LOCAL.get().get(contextClass)) != null) && (!contextStack.isEmpty());
  }

  public static  C getContext (Class contextClass)
    throws ContextException {

    ContextStack contextStack;
    C context;

    if (((contextStack = CONTEXT_MAP_LOCAL.get().get(contextClass)) == null) || ((context = contextStack.peek()) == null)) {

      return null;
    }

    return context;
  }

  public static Context[] getContextsOn (Method method) {

    return getContextsOn(method, Context.class);
  }

  public static Context[] getContextsOn (Method method, Class... baseContextClasses)
    throws ContextException {

    Context[] contexts;
    ExpectedContexts expectedContexts;
    HashSet> requiredClasses = new HashSet<>();
    LinkedList contextList = new LinkedList<>();

    if ((expectedContexts = method.getAnnotation(ExpectedContexts.class)) != null) {
      requiredClasses.addAll(Arrays.asList(expectedContexts.value()));
    }

    for (Map.Entry, ContextStack> contextEntry : CONTEXT_MAP_LOCAL.get().entrySet()) {

      Context context;

      for (Class baseContextClass : baseContextClasses) {
        if (baseContextClass.isAssignableFrom(contextEntry.getKey())) {
          if ((context = contextEntry.getValue().peek()) != null) {
            requiredClasses.remove(contextEntry.getKey());
            contextList.add(context);
          }
          break;
        }
      }
    }

    if (!requiredClasses.isEmpty()) {
      throw new ContextException("Context(%s) has not been instantiated", requiredClasses.iterator().next());
    }

    contexts = new Context[contextList.size()];
    contextList.toArray(contexts);

    return contexts;
  }

  public static  void pushContext (C context) {

    ContextStack contextStack;

    if ((contextStack = CONTEXT_MAP_LOCAL.get().get(context.getClass())) == null) {
      CONTEXT_MAP_LOCAL.get().put(context.getClass(), contextStack = new ContextStack<>());
    }

    contextStack.push(context);
  }

  public static Context popContext (Context context) {

    return popContext(context.getClass());
  }

  public static  C popContext (Class contextClass) {

    ContextStack contextStack;

    if ((contextStack = CONTEXT_MAP_LOCAL.get().get(contextClass)) != null) {
      return contextStack.pop();
    }

    return null;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy