001    /*
002     * Copyright 2010-2013 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.jet.lang.resolve.calls.inference;
018    
019    import com.google.common.collect.Lists;
020    import com.google.common.collect.Maps;
021    import com.intellij.openapi.util.Condition;
022    import com.intellij.util.containers.ContainerUtil;
023    import org.jetbrains.annotations.NotNull;
024    
025    import java.util.Collection;
026    import java.util.Map;
027    
028    public class ConstraintPosition {
029        public static final ConstraintPosition RECEIVER_POSITION = new ConstraintPosition("RECEIVER_POSITION", true);
030        public static final ConstraintPosition EXPECTED_TYPE_POSITION = new ConstraintPosition("EXPECTED_TYPE_POSITION", true);
031        public static final ConstraintPosition FROM_COMPLETER = new ConstraintPosition("FROM_COMPLETER", true);
032        public static final ConstraintPosition SPECIAL = new ConstraintPosition("SPECIAL", true);
033    
034        private static final Map<Integer, ConstraintPosition> valueParameterPositions = Maps.newHashMap();
035        private static final Map<Integer, ConstraintPosition> typeBoundPositions = Maps.newHashMap();
036    
037        public static ConstraintPosition getValueParameterPosition(int index) {
038            ConstraintPosition position = valueParameterPositions.get(index);
039            if (position == null) {
040                position = new ConstraintPosition("VALUE_PARAMETER_POSITION(" + index + ")", true);
041                valueParameterPositions.put(index, position);
042            }
043            return position;
044        }
045    
046        public static ConstraintPosition getTypeBoundPosition(int index) {
047            ConstraintPosition position = typeBoundPositions.get(index);
048            if (position == null) {
049                position = new ConstraintPosition("TYPE_BOUND_POSITION(" + index + ")", false);
050                typeBoundPositions.put(index, position);
051            }
052            return position;
053        }
054    
055        public static class CompoundConstraintPosition extends ConstraintPosition {
056            private final Collection<ConstraintPosition> positions;
057    
058            public CompoundConstraintPosition(Collection<ConstraintPosition> positions) {
059                super("COMPOUND_CONSTRAINT_POSITION", hasConstraint(positions, /*strong=*/true));
060                this.positions = positions;
061            }
062    
063            public boolean consistsOfOnlyStrongConstraints() {
064                return !hasConstraint(positions, /*strong=*/false);
065            }
066    
067            private static boolean hasConstraint(@NotNull Collection<ConstraintPosition> positions, final boolean strong) {
068                return ContainerUtil.exists(positions, new Condition<ConstraintPosition>() {
069                    @Override
070                    public boolean value(ConstraintPosition constraintPosition) {
071                        return constraintPosition.isStrong() == strong;
072                    }
073                });
074            }
075        }
076    
077        public static ConstraintPosition getCompoundConstraintPosition(ConstraintPosition... positions) {
078            return new CompoundConstraintPosition(Lists.newArrayList(positions));
079        }
080    
081        private final String debugName;
082        private final boolean isStrong;
083    
084        private ConstraintPosition(String name, boolean isStrong) {
085            debugName = name;
086            this.isStrong = isStrong;
087        }
088    
089        public boolean isStrong() {
090            return isStrong;
091        }
092    
093        @Override
094        public String toString() {
095            return debugName;
096        }
097    }