update copyrights
[fedora-idea.git] / platform / lang-impl / src / com / intellij / psi / impl / meta / MetaRegistry.java
blob580907d57b4433b804e1d02e0bb8034fc29ce25f
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.psi.impl.meta;
19 import com.intellij.openapi.Disposable;
20 import com.intellij.openapi.extensions.Extensions;
21 import com.intellij.openapi.progress.ProgressManager;
22 import com.intellij.openapi.util.Disposer;
23 import com.intellij.openapi.util.Key;
24 import com.intellij.openapi.util.UserDataCache;
25 import com.intellij.patterns.ElementPattern;
26 import com.intellij.psi.PsiElement;
27 import com.intellij.psi.util.CachedValue;
28 import com.intellij.psi.util.CachedValueProvider;
29 import com.intellij.psi.filters.ElementFilter;
30 import com.intellij.psi.filters.position.PatternFilter;
31 import com.intellij.psi.meta.MetaDataContributor;
32 import com.intellij.psi.meta.MetaDataRegistrar;
33 import com.intellij.psi.meta.PsiMetaData;
34 import com.intellij.util.containers.ContainerUtil;
35 import org.jetbrains.annotations.NotNull;
36 import org.jetbrains.annotations.Nullable;
38 import java.util.List;
40 /**
41 * Created by IntelliJ IDEA.
42 * User: ik
43 * Date: 07.05.2003
44 * Time: 3:31:09
45 * To change this template use Options | File Templates.
47 public class MetaRegistry extends MetaDataRegistrar {
48 private static final List<MyBinding> ourBindings = ContainerUtil.createEmptyCOWList();
49 private static volatile boolean ourContributorsLoaded = false;
51 private static final Key<CachedValue<PsiMetaData>> META_DATA_KEY = Key.create("META DATA KEY");
53 public static void bindDataToElement(final PsiElement element, final PsiMetaData data) {
54 CachedValue<PsiMetaData> value =
55 element.getManager().getCachedValuesManager().createCachedValue(new CachedValueProvider<PsiMetaData>() {
56 public Result<PsiMetaData> compute() {
57 data.init(element);
58 return new Result<PsiMetaData>(data, data.getDependences());
60 });
61 element.putUserData(META_DATA_KEY, value);
64 public static PsiMetaData getMeta(final PsiElement element) {
65 final PsiMetaData base = getMetaBase(element);
66 return base != null ? base : null;
69 private static final UserDataCache<CachedValue<PsiMetaData>, PsiElement, Object> ourCachedMetaCache =
70 new UserDataCache<CachedValue<PsiMetaData>, PsiElement, Object>() {
71 protected CachedValue<PsiMetaData> compute(final PsiElement element, Object p) {
72 return element.getManager().getCachedValuesManager()
73 .createCachedValue(new CachedValueProvider<PsiMetaData>() {
74 public Result<PsiMetaData> compute() {
75 try {
76 ensureContributorsLoaded();
77 for (final MyBinding binding : ourBindings) {
78 if (binding.myFilter.isClassAcceptable(element.getClass()) && binding.myFilter.isAcceptable(element, element.getParent())) {
79 final PsiMetaData data = binding.myDataClass.newInstance();
80 data.init(element);
81 return new Result<PsiMetaData>(data, data.getDependences());
85 catch (IllegalAccessException iae) {
86 throw new RuntimeException(iae);
88 catch (InstantiationException ie) {
89 throw new RuntimeException(ie);
92 return new Result<PsiMetaData>(null, element);
94 }, false);
98 private static void ensureContributorsLoaded() {
99 if (!ourContributorsLoaded) {
100 synchronized (ourBindings) {
101 if (!ourContributorsLoaded) {
102 for(MetaDataContributor contributor: Extensions.getExtensions(MetaDataContributor.EP_NAME)) {
103 contributor.contributeMetaData(MetaDataRegistrar.getInstance());
105 ourContributorsLoaded = true;
111 @Nullable
112 public static PsiMetaData getMetaBase(final PsiElement element) {
113 ProgressManager.getInstance().checkCanceled();
114 return ourCachedMetaCache.get(META_DATA_KEY, element, null).getValue();
117 public static <T extends PsiMetaData> void addMetadataBinding(ElementFilter filter, Class<T> aMetadataClass, Disposable parentDisposable) {
118 final MyBinding binding = new MyBinding(filter, aMetadataClass);
119 addBinding(binding);
120 Disposer.register(parentDisposable, new Disposable() {
121 public void dispose() {
122 ourBindings.remove(binding);
127 public static <T extends PsiMetaData> void addMetadataBinding(ElementFilter filter, Class<T> aMetadataClass) {
128 addBinding(new MyBinding(filter, aMetadataClass));
131 private static void addBinding(final MyBinding binding) {
132 ourBindings.add(0, binding);
135 public <T extends PsiMetaData> void registerMetaData(ElementFilter filter, Class<T> metadataDescriptorClass) {
136 addMetadataBinding(filter, metadataDescriptorClass);
139 @Override
140 public <T extends PsiMetaData> void registerMetaData(ElementPattern<?> pattern, Class<T> metadataDescriptorClass) {
141 addMetadataBinding(new PatternFilter(pattern), metadataDescriptorClass);
144 private static class MyBinding {
145 private final ElementFilter myFilter;
146 private final Class<? extends PsiMetaData> myDataClass;
148 public MyBinding(@NotNull ElementFilter filter, @NotNull Class<? extends PsiMetaData> dataClass) {
149 myFilter = filter;
150 myDataClass = dataClass;