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.2.0
Show newest version
/*
 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 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, LinkedList>> CONTEXT_MAP_LOCAL = new InheritableThreadLocal<>() {

    @Override
    protected Map, LinkedList> initialValue () {

      return new HashMap<>();
    }

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

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

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

    LinkedList contextStack;

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

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

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

  public static  C[] exportContextTrace (Class contextClass) {

    C[] contexts;
    C context;
    LinkedList exportedList;
    LinkedList contextStack;

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

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

    return contexts;
  }

  public static  void clearContextTrace (Class contextClass) {

    LinkedList contextStack;

    if ((contextStack = (LinkedList)CONTEXT_MAP_LOCAL.get().get(contextClass)) != null) {
      contextStack.clear();
    }
  }

  public static  boolean exists (Class contextClass) {

    LinkedList contextStack;

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

  public static  C getContext (Class contextClass)
    throws ContextException {

    LinkedList contextStack;
    C context;

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

      return null;
    }

    return context;
  }

  public static Context[] filterContextsOn (Method method) {

    return filterContextsOn(method, Context.class);
  }

  public static Context[] filterContextsOn (Method method, Class... filterClasses)
    throws ContextException {

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

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

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

      Context context;

      for (Class filterClass : filterClasses) {
        if (filterClass.isAssignableFrom(contextEntry.getKey())) {
          if ((context = contextEntry.getValue().peek()) != null) {
            expectedClasses.remove(contextEntry.getKey());
            contextList.add(context);
          }
          break;
        }
      }
    }

    if (!expectedClasses.isEmpty()) {
      throw new ContextException("The context expectations(%s) have not been satisfied", Arrays.toString(expectedClasses.toArray()));
    }

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

    return contexts;
  }

  public static  void pushContext (C context) {

    LinkedList contextStack;

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

    contextStack.push(context);
  }

  public static  C popContext (Class contextClass) {

    LinkedList contextStack;

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

    return null;
  }

  public static Context removeContext (Context context) {

    LinkedList contextStack;

    if ((contextStack = CONTEXT_MAP_LOCAL.get().get(context.getClass())) != null) {
      if (contextStack.remove(context)) {

        return context;
      }
    }

    return null;
  }

  public static  int sizeFor (Class contextClass) {

    LinkedList contextStack;

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

    return 0;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy