diff --git a/json/src/com/jetbrains/jsonSchema/JsonSchemaPatternComparator.java b/json/src/com/jetbrains/jsonSchema/JsonSchemaPatternComparator.java new file mode 100644 index 000000000000..663259f503f6 --- /dev/null +++ b/json/src/com/jetbrains/jsonSchema/JsonSchemaPatternComparator.java @@ -0,0 +1,108 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.jsonSchema; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.BeforeAfter; +import com.intellij.util.ThreeState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; + +/** + * @author Irina.Chernushina on 2/17/2016. + */ +public class JsonSchemaPatternComparator { + @NotNull + private final Project myProject; + + public JsonSchemaPatternComparator(@NotNull Project project) { + myProject = project; + } + + @NotNull + public ThreeState isSimilar(@NotNull JsonSchemaMappingsConfigurationBase.Item itemLeft, + @NotNull JsonSchemaMappingsConfigurationBase.Item itemRight) { + if (itemLeft.isPattern() != itemRight.isPattern()) return ThreeState.NO; + if (itemLeft.isPattern()) return comparePatterns(itemLeft, itemRight); + return comparePaths(itemLeft, itemRight); + } + + private ThreeState comparePaths(JsonSchemaMappingsConfigurationBase.Item left, JsonSchemaMappingsConfigurationBase.Item right) { + final File leftFile = new File(myProject.getBasePath(), left.getPath()); + final File rightFile = new File(myProject.getBasePath(), right.getPath()); + + if (left.isDirectory()) { + if (FileUtil.isAncestor(leftFile, rightFile, true)) return ThreeState.YES; + } + if (right.isDirectory()) { + if (FileUtil.isAncestor(rightFile, leftFile, true)) return ThreeState.YES; + } + return FileUtil.filesEqual(leftFile, rightFile) && left.isDirectory() == right.isDirectory() ? ThreeState.YES : ThreeState.NO; + } + + private static ThreeState comparePatterns(JsonSchemaMappingsConfigurationBase.Item left, JsonSchemaMappingsConfigurationBase.Item right) { + if (left.getPath().equals(right.getPath())) return ThreeState.YES; + final BeforeAfter beforeAfterLeft = getBeforeAfterAroundWildCards(left.getPath()); + final BeforeAfter beforeAfterRight = getBeforeAfterAroundWildCards(right.getPath()); + if (beforeAfterLeft == null || beforeAfterRight == null) { + if (beforeAfterLeft == null && beforeAfterRight == null) return left.getPath().equals(right.getPath()) ? ThreeState.YES : ThreeState.NO; + if (beforeAfterLeft == null) { + return checkOneSideWithoutWildcard(left, beforeAfterRight); + } + return checkOneSideWithoutWildcard(right, beforeAfterLeft); + } + if (!StringUtil.isEmptyOrSpaces(beforeAfterLeft.getBefore()) && !StringUtil.isEmptyOrSpaces(beforeAfterRight.getBefore())) { + if (beforeAfterLeft.getBefore().startsWith(beforeAfterRight.getBefore()) || + beforeAfterRight.getBefore().startsWith(beforeAfterLeft.getBefore())) { + return ThreeState.YES; + } + // otherwise they are different + return ThreeState.NO; + } + if (!StringUtil.isEmptyOrSpaces(beforeAfterLeft.getAfter()) && !StringUtil.isEmptyOrSpaces(beforeAfterRight.getAfter())) { + if (beforeAfterLeft.getAfter().endsWith(beforeAfterRight.getAfter()) || + beforeAfterRight.getAfter().endsWith(beforeAfterLeft.getAfter())) { + return ThreeState.YES; + } + // otherwise they are different + return ThreeState.NO; + } + return ThreeState.UNSURE; + } + + @NotNull + private static ThreeState checkOneSideWithoutWildcard(JsonSchemaMappingsConfigurationBase.Item item, BeforeAfter beforeAfter) { + if (!StringUtil.isEmptyOrSpaces(beforeAfter.getBefore()) && item.getPath().startsWith(beforeAfter.getBefore())) { + return ThreeState.YES; + } + if (!StringUtil.isEmptyOrSpaces(beforeAfter.getAfter()) && item.getPath().endsWith(beforeAfter.getAfter())) { + return ThreeState.YES; + } + return ThreeState.UNSURE; + } + + @Nullable + private static BeforeAfter getBeforeAfterAroundWildCards(@NotNull final String pattern) { + final int firstIdx = pattern.indexOf('*'); + final int lastIdx = pattern.lastIndexOf('*'); + if (firstIdx < 0 || lastIdx < 0) return null; + return new BeforeAfter<>(pattern.substring(0, firstIdx), pattern.substring(lastIdx + 1, pattern.length())); + } +} diff --git a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaPatternComparatorTest.java b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaPatternComparatorTest.java new file mode 100644 index 000000000000..c9270aa116de --- /dev/null +++ b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaPatternComparatorTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jetbrains.jsonSchema; + +import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import com.intellij.util.ThreeState; +import org.jetbrains.annotations.NotNull; +import org.junit.Assert; + +/** + * @author Irina.Chernushina on 2/17/2016. + */ +public class JsonSchemaPatternComparatorTest extends LightPlatformCodeInsightFixtureTestCase { + public void testPatterns() throws Exception { + final JsonSchemaPatternComparator comparator = new JsonSchemaPatternComparator(getProject()); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(p("test"), p("test"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(p("test"), p("tes*"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(p("tes*"), p("test"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(p("test"), p("*est"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(p("testwords"), p("test*words"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(p("testwords"), p("*test*words"))); + Assert.assertEquals(ThreeState.NO, comparator.isSimilar(p("*.abc"), p("*.cde"))); + Assert.assertEquals(ThreeState.UNSURE, comparator.isSimilar(p("*.abc"), p("start.*"))); + Assert.assertEquals(ThreeState.UNSURE, comparator.isSimilar(p("two*words"), p("circus"))); + } + + public void test2Files() throws Exception { + final JsonSchemaPatternComparator comparator = new JsonSchemaPatternComparator(getProject()); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(f("test"), f("test"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(f("./test"), f("test"))); + Assert.assertEquals(ThreeState.NO, comparator.isSimilar(f("../test"), f("test"))); + Assert.assertEquals(ThreeState.NO, comparator.isSimilar(f("other"), f("test"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(f("one/../one/two"), f("one/two"))); + } + + public void test2Dirs() throws Exception { + final JsonSchemaPatternComparator comparator = new JsonSchemaPatternComparator(getProject()); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(d("test"), d("test"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(d("./test"), d("test"))); + Assert.assertEquals(ThreeState.NO, comparator.isSimilar(d("../test"), d("test"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(d(".."), d("test"))); + Assert.assertEquals(ThreeState.NO, comparator.isSimilar(d("another"), d("test"))); + + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(d("test/child"), d("test"))); + } + + public void testDirAndFile() throws Exception { + final JsonSchemaPatternComparator comparator = new JsonSchemaPatternComparator(getProject()); + Assert.assertEquals(ThreeState.NO, comparator.isSimilar(d("test"), f("test"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(d("test"), f("test/lower"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(d("test"), f("./test/lower"))); + Assert.assertEquals(ThreeState.YES, comparator.isSimilar(d(".."), f("test/lower"))); + Assert.assertEquals(ThreeState.NO, comparator.isSimilar(d("one"), f("test/lower"))); + Assert.assertEquals(ThreeState.NO, comparator.isSimilar(d("one"), f("test"))); + } + + private static JsonSchemaMappingsConfigurationBase.Item p(@NotNull final String p) { + return new JsonSchemaMappingsConfigurationBase.Item(p, true, false); + } + + private static JsonSchemaMappingsConfigurationBase.Item d(@NotNull final String d) { + return new JsonSchemaMappingsConfigurationBase.Item(d, false, true); + } + + private static JsonSchemaMappingsConfigurationBase.Item f(@NotNull final String f) { + return new JsonSchemaMappingsConfigurationBase.Item(f, false, false); + } +}