001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.config;
018    
019    import com.intellij.openapi.util.Key;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    
023    import java.util.*;
024    
025    @SuppressWarnings("unchecked")
026    public class CompilerConfiguration {
027        private final Map<Key, Object> map = new HashMap<Key, Object>();
028        private boolean readOnly = false;
029    
030        @Nullable
031        public <T> T get(@NotNull CompilerConfigurationKey<T> key) {
032            T data = (T) map.get(key.ideaKey);
033            return data == null ? null : unmodifiable(data);
034        }
035    
036        @NotNull
037        public <T> T get(@NotNull CompilerConfigurationKey<T> key, @NotNull T defaultValue) {
038            T data = (T) map.get(key.ideaKey);
039            return data == null ? defaultValue : unmodifiable(data);
040        }
041    
042        @NotNull
043        public <T> List<T> getList(@NotNull CompilerConfigurationKey<List<T>> key) {
044            List<T> data = (List<T>) map.get(key.ideaKey);
045            if (data == null) {
046                return Collections.emptyList();
047            }
048            else {
049                return Collections.unmodifiableList(data);
050            }
051        }
052    
053        public <T> void put(@NotNull CompilerConfigurationKey<T> key, @Nullable T value) {
054            checkReadOnly();
055            map.put(key.ideaKey, value);
056        }
057    
058        public <T> void add(@NotNull CompilerConfigurationKey<List<T>> key, @NotNull T value) {
059            checkReadOnly();
060            Key<List<T>> ideaKey = key.ideaKey;
061            if (map.get(ideaKey) == null) {
062                map.put(ideaKey, new ArrayList<T>());
063            }
064            List<T> list = (List<T>) map.get(ideaKey);
065            list.add(value);
066        }
067    
068        public <T> void addAll(@NotNull CompilerConfigurationKey<List<T>> key, @NotNull Collection<T> values) {
069            checkReadOnly();
070            checkForNullElements(values);
071            Key<List<T>> ideaKey = key.ideaKey;
072            if (map.get(ideaKey) == null) {
073                map.put(ideaKey, new ArrayList<T>());
074            }
075            List<T> list = (List<T>) map.get(ideaKey);
076            list.addAll(values);
077        }
078    
079        public CompilerConfiguration copy() {
080            CompilerConfiguration copy = new CompilerConfiguration();
081            copy.map.putAll(map);
082            return copy;
083        }
084    
085        private void checkReadOnly() {
086            if (readOnly) {
087                throw new IllegalStateException("CompilerConfiguration is read-only");
088            }
089        }
090    
091        public void setReadOnly(boolean readOnly) {
092            if (readOnly != this.readOnly) {
093                checkReadOnly();
094                this.readOnly = readOnly;
095            }
096        }
097    
098        @NotNull
099        private static <T> T unmodifiable(@NotNull T object) {
100            if (object instanceof List) {
101                return (T) Collections.unmodifiableList((List) object);
102            }
103            else if (object instanceof Map) {
104                return (T) Collections.unmodifiableMap((Map) object);
105            }
106            else if (object instanceof Collection) {
107                return (T) Collections.unmodifiableCollection((Collection) object);
108            }
109            else {
110                return object;
111            }
112        }
113    
114        @Override
115        public String toString() {
116            return map.toString();
117        }
118    
119        private static <T> void checkForNullElements(Collection<T> values) {
120            int index = 0;
121            for (T value : values) {
122                if (value == null) {
123                    throw new IllegalArgumentException("Element " + index
124                                                       + " is null, while null values in compiler configuration are not allowed");
125                }
126                index++;
127            }
128        }
129    }