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
017package org.jetbrains.k2js.translate.intrinsic.functions.patterns;
018
019import com.google.common.collect.Lists;
020import org.jetbrains.annotations.NotNull;
021import org.jetbrains.annotations.Nullable;
022import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
023import org.jetbrains.jet.lang.resolve.DescriptorUtils;
024import org.jetbrains.jet.lang.resolve.name.Name;
025
026import java.util.Arrays;
027import java.util.List;
028
029public final class PatternBuilder {
030
031    @NotNull
032    private static final NamePredicate JET = new NamePredicate("jet");
033
034    private PatternBuilder() {
035    }
036
037    @NotNull
038    public static DescriptorPredicate pattern(@NotNull NamePredicate checker, @NotNull String stringWithPattern) {
039        List<NamePredicate> checkers = Lists.newArrayList(checker);
040        checkers.addAll(parseStringAsCheckerList(stringWithPattern));
041        return pattern(checkers);
042    }
043
044    @NotNull
045    public static DescriptorPredicate pattern(@NotNull String stringWithPattern, @NotNull NamePredicate checker) {
046        List<NamePredicate> checkers = Lists.newArrayList(parseStringAsCheckerList(stringWithPattern));
047        checkers.add(checker);
048        return pattern(checkers);
049    }
050
051    @NotNull
052    public static DescriptorPredicate pattern(@NotNull String string) {
053        List<NamePredicate> checkers = parseStringAsCheckerList(string);
054        return pattern(checkers);
055    }
056
057    @NotNull
058    private static List<NamePredicate> parseStringAsCheckerList(@NotNull String stringWithPattern) {
059        String[] subPatterns = stringWithPattern.split("\\.");
060        List<NamePredicate> checkers = Lists.newArrayList();
061        for (String subPattern : subPatterns) {
062            String[] validNames = subPattern.split("\\|");
063            checkers.add(new NamePredicate(validNames));
064        }
065        return checkers;
066    }
067
068    @NotNull
069    private static DescriptorPredicate pattern(@NotNull List<NamePredicate> checkers) {
070        final List<NamePredicate> checkersWithPrefixChecker = Lists.newArrayList(JET);
071        checkersWithPrefixChecker.addAll(checkers);
072        return new DescriptorPredicate() {
073            @Override
074            public boolean apply(@Nullable FunctionDescriptor descriptor) {
075                assert descriptor != null;
076                //TODO: no need to wrap if we check beforehand
077                try {
078                    return doApply(descriptor);
079                }
080                catch (IllegalArgumentException e) {
081                    return false;
082                }
083            }
084
085            private boolean doApply(@NotNull FunctionDescriptor descriptor) {
086                List<Name> nameParts = DescriptorUtils.getFQName(descriptor).pathSegments();
087                if (nameParts.size() != checkersWithPrefixChecker.size()) {
088                    return false;
089                }
090                if (!allNamePartsValid(nameParts)) return false;
091                return true;
092            }
093
094            private boolean allNamePartsValid(@NotNull List<Name> nameParts) {
095                for (int i = 0; i < nameParts.size(); ++i) {
096                    Name namePart = nameParts.get(i);
097                    NamePredicate correspondingPredicate = checkersWithPrefixChecker.get(i);
098                    if (!correspondingPredicate.apply(namePart)) {
099                        return false;
100                    }
101                }
102                return true;
103            }
104        };
105    }
106
107    @NotNull
108    public static DescriptorPredicate pattern(@NotNull NamePredicate... checkers) {
109        return pattern(Arrays.asList(checkers));
110    }
111}