// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util;

import com.intellij.openapi.util.Key;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Map;

/**
 * A wrapper around map, allowing to put and get values by keys in a type-safe way. Used in various extension implementations
 * to manage temporary state. For example:
 * <ul>
 * <li>When creating ElementPattern, processing context may be used to cache some intermediate data
 * to be shared between pattern parts.</li>
 * <li>Some extensions (e.g, PsiReferenceProvider, CompletionContributors) use per-pattern registration. That allows to use
 * ElementPattern#save to put matched objects into processing contexts and then retrieve those objects inside extension implementation
 * after the matching is complete.</li>
 * </ul>
 * 
 * Simple processing context can contain a shared processing context inside, which should be used when iterating over several patterns 
 * or extensions, possibly from different plugins. They may still wish to reuse some cached information that a previous extension has already calculated.
 * <p/>
 * In this case, a separate ProcessingContext object is created for each of those extensions, but the same {@link SharedProcessingContext}
 * is passed to their constructors. To reuse shared context, extensions are required to work with {@link #getSharedContext()} result.
 * <p/>
 * Not thread-safe.
 *
 * @see #get(Key) 
 * @see #put(Key, Object)
 * @see #ProcessingContext(SharedProcessingContext) 
 * @author peter
 */
public class ProcessingContext {
  private Map<Object, Object> myMap;
  private SharedProcessingContext mySharedContext;

  public ProcessingContext() {
  }

  public ProcessingContext(final SharedProcessingContext sharedContext) {
    mySharedContext = sharedContext;
  }

  @NotNull
  public SharedProcessingContext getSharedContext() {
    if (mySharedContext == null) {
      return mySharedContext = new SharedProcessingContext();
    }
    return mySharedContext;
  }

  public Object get(@NotNull @NonNls final Object key) {
    return myMap == null? null : myMap.get(key);
  }

  public void put(@NotNull @NonNls final Object key, @NotNull final Object value) {
    checkMapInitialized();
    myMap.put(key, value);
  }

  public <T> void put(Key<T> key, T value) {
    checkMapInitialized();
    myMap.put(key, value);
  }

  public <T> T get(Key<T> key) {
    return myMap == null ? null : (T)myMap.get(key);
  }

  private void checkMapInitialized() {
    if (myMap == null) myMap = new HashMap<>(1);
  }

}

@@ -17,10 +17,10 @@
 0-20
-19
+20
  Jet
@@ -535,16 +535,23 @@
 reating 
+%7B@code 
 ElementP
@@ -556,16 +556,17 @@
 tPattern
+%7D
 , proces
@@ -694,16 +694,23 @@
 ns (e.g,
+ %7B@code
  PsiRefe
@@ -722,17 +722,25 @@
 Provider
+%7D
 ,
+ %7B@code
  Complet
@@ -754,16 +754,17 @@
 ributors
+%7D
 ) use pe
@@ -808,16 +808,23 @@
 o use%0A *
+ %7B@code
  Element
@@ -835,16 +835,17 @@
 ern#save
+%7D
  to put 
@@ -1293,25 +1293,24 @@
 lated.%0A * %3Cp
-/
 %3E%0A * In this
@@ -1580,10 +1580,10 @@
  * %3C
-p
 /
+p
 %3E%0A *

fix javadoc formatting