/*
* Copyright (c) 2015-2015 Vladimir Schneider <vladimir.schneider@gmail.com>
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.vladsch.idea.multimarkdown.spellchecking;
import com.intellij.openapi.project.Project;
import groovy.lang.Sequence;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
public class SuggestionList {
final protected @NotNull ArrayList<Suggestion> suggestions = new ArrayList<Suggestion>();
final protected @NotNull HashSet<String> suggestionSet = new HashSet<String>();
final protected @Nullable Project project;
final public static SuggestionList EMPTY_LIST = new SuggestionList();
public SuggestionList(@Nullable Project project) {
this.project = project;
}
public SuggestionList() {
project = null;
}
public SuggestionList(@NotNull SuggestionList other) {
this(other.project);
add(other);
}
public int size() {
return suggestions.size();
}
public SuggestionList add(Suggestion... suggestions) {
for (Suggestion suggestion : suggestions) {
String suggestionText = suggestion.getText();
if (!this.suggestionSet.contains(suggestionText)) {
this.suggestions.add(suggestion);
this.suggestionSet.add(suggestionText);
}
}
return this;
}
public SuggestionList add(SuggestionList... suggestionLists) {
for (SuggestionList suggestionList : suggestionLists) {
for (Suggestion suggestion : suggestionList.suggestions) {
String suggestionText = suggestion.getText();
if (!this.suggestionSet.contains(suggestionText)) {
this.suggestions.add(suggestion);
this.suggestionSet.add(suggestionText);
}
}
}
return this;
}
public SuggestionList addAll(String... suggestionTexts) {
for (String suggestionText : suggestionTexts) {
if (suggestionText != null && !this.suggestionSet.contains(suggestionText)) {
this.suggestions.add(new Suggestion(suggestionText));
this.suggestionSet.add(suggestionText);
}
}
return this;
}
public SuggestionList add(@Nullable String suggestionText) {
if (suggestionText != null && !this.suggestionSet.contains(suggestionText)) {
this.suggestions.add(new Suggestion(suggestionText));
this.suggestionSet.add(suggestionText);
}
return this;
}
public SuggestionList add(@Nullable String suggestionText, Suggestion... sourceSuggestions) {
if (suggestionText != null && !this.suggestionSet.contains(suggestionText)) {
this.suggestions.add(new Suggestion(suggestionText, sourceSuggestions));
this.suggestionSet.add(suggestionText);
}
return this;
}
public SuggestionList add(@Nullable String suggestionText, @NotNull Suggestion.Param param, Suggestion... sourceSuggestions) {
if (suggestionText != null && !this.suggestionSet.contains(suggestionText)) {
this.suggestions.add(new Suggestion(suggestionText, param, sourceSuggestions));
this.suggestionSet.add(suggestionText);
}
return this;
}
@NotNull
public List<String> asList() {
ArrayList<String> list = new ArrayList<String>();
for (Suggestion suggestion : suggestions) {
list.add(suggestion.getText());
}
return list;
}
@NotNull
public ArrayList<Suggestion> getSuggestions() {
return suggestions;
}
@Nullable
protected SuggestionList chainFixers(int index, SuggestionList inList, Suggestion.Fixer... fixers) {
Suggestion.Fixer fixer;
do {
if (fixers.length <= index) {
return inList;
}
fixer = fixers[index++];
}
while (fixer == null);
SuggestionList resultList = new SuggestionList(this.project);
for (Suggestion suggestion : inList.getSuggestions()) {
if (suggestion.isEmpty()) continue;
SuggestionList outList = fixer.fix(suggestion, project);
if (outList != null) {
outList = chainFixers(index, outList, fixers);
if (outList != null) {
resultList.add(outList);
}
}
}
return resultList;
}
@NotNull
public SuggestionList chainFixers(Suggestion.Fixer... fixers) {
SuggestionList suggestionList = chainFixers(0, this, fixers);
return suggestionList == null ? new SuggestionList(this.project) : suggestionList;
}
@NotNull
public SuggestionList batchFixers(Suggestion.Fixer... fixers) {
SuggestionList result = new SuggestionList(this.project);
for (Suggestion.Fixer fixer : fixers) {
if (fixer == null) continue;
for (Suggestion suggestion : getSuggestions()) {
if (suggestion.isEmpty()) continue;
SuggestionList fixedList = fixer.fix(suggestion, project);
if (fixedList != null) result.add(fixedList);
}
}
return result;
}
@NotNull
public SuggestionList sequenceFixers(Suggestion.Fixer... fixers) {
SuggestionList result = new SuggestionList(this.project);
for (Suggestion suggestion : getSuggestions()) {
if (suggestion.isEmpty()) continue;
for (Suggestion.Fixer fixer : fixers) {
if (fixer == null) continue;
SuggestionList fixedList = fixer.fix(suggestion, project);
if (fixedList != null) result.add(fixedList);
}
}
return result;
}
@NotNull
public SuggestionList prefix(@Nullable String prefix) {
return wrap(prefix, null);
}
@NotNull
public SuggestionList suffix(@Nullable String suffix) {
return wrap(null, suffix);
}
@NotNull
public SuggestionList prefixAlign(@Nullable SuggestionList prefixes) {
return wrapAlign(prefixes, null);
}
@NotNull
public SuggestionList suffixAlign(@Nullable SuggestionList suffixes) {
return wrapAlign(null, suffixes);
}
@NotNull
public SuggestionList prefixPermute(@Nullable SuggestionList prefixes) {
return wrapPermute(prefixes, null);
}
@NotNull
public SuggestionList suffixPermute(@Nullable SuggestionList suffixes) {
return wrapPermute(null, suffixes);
}
// TEST: needs a test
@NotNull
public SuggestionList wrap(@Nullable String prefix, @Nullable String suffix) {
SuggestionList prefixedList;
if ((prefix == null || prefix.isEmpty()) && (suffix == null || suffix.isEmpty())) {
prefixedList = new SuggestionList(this);
} else {
prefixedList = new SuggestionList(this.project);
if (prefix == null) prefix = "";
if (suffix == null) suffix = "";
for (Suggestion suggestion : suggestions) {
prefixedList.add(prefix + suggestion.getText() + suffix, suggestion);
}
}
return prefixedList;
}
public boolean isEmpty() {
return suggestions.isEmpty();
}
// TEST: needs a test
@NotNull
public SuggestionList wrapPermute(@Nullable SuggestionList prefixes, @Nullable SuggestionList suffixes) {
SuggestionList wrappedList = new SuggestionList(project);
if (prefixes != null && !prefixes.isEmpty() && suffixes != null && !suffixes.isEmpty()) {
for (Suggestion prefix : prefixes.suggestions) {
for (Suggestion suffix : suffixes.suggestions) {
for (Suggestion suggestion : suggestions) {
wrappedList.add(prefix.getText() + suggestion.getText() + suffix.getText(), prefix, suffix);
}
}
}
} else if (suffixes != null && !suffixes.isEmpty()) {
for (Suggestion suffix : suffixes.suggestions) {
for (Suggestion suggestion : suggestions) {
wrappedList.add(suggestion.getText() + suffix.getText(), suffix);
}
}
} else if (prefixes != null && !prefixes.isEmpty()) {
for (Suggestion prefix : prefixes.suggestions) {
for (Suggestion suggestion : suggestions) {
wrappedList.add(prefix.getText() + suggestion.getText(), prefix);
}
}
}
return wrappedList;
}
// TEST: needs a test
@NotNull
public SuggestionList wrapAlign(@Nullable SuggestionList prefixes, @Nullable SuggestionList suffixes) {
SuggestionList wrappedList = new SuggestionList(project);
if (prefixes != null && !prefixes.isEmpty() && suffixes != null && !suffixes.isEmpty()) {
int iMax = Math.min(Math.min(prefixes.size(), suffixes.size()), size());
for (int i = 0; i < iMax; i++) {
Suggestion suggestion = suggestions.get(i);
Suggestion prefix = prefixes.suggestions.get(i);
Suggestion suffix = suffixes.suggestions.get(i);
wrappedList.add(prefix.getText() + suggestion.getText() + suffix.getText(), prefix, suggestion, suffix);
}
} else if (suffixes != null && !suffixes.isEmpty()) {
int iMax = Math.min(suffixes.size(), size());
for (int i = 0; i < iMax; i++) {
Suggestion suggestion = suggestions.get(i);
Suggestion suffix = suffixes.suggestions.get(i);
wrappedList.add(suggestion.getText() + suffix.getText(), suggestion, suffix);
}
} else if (prefixes != null && !prefixes.isEmpty()) {
int iMax = Math.min(prefixes.size(), size());
for (int i = 0; i < iMax; i++) {
Suggestion suggestion = suggestions.get(i);
Suggestion prefix = prefixes.suggestions.get(i);
wrappedList.add(prefix.getText() + suggestion.getText(), prefix, suggestion);
}
}
return wrappedList;
}
// TEST: needs a test
/*
returns a list that permutes suggestions from this list, prefixed and suffixed.
filters applied to prefixes and suffixes and permutations happen on the fixed prefix and suffixed lists by applying a single fixer to both lists and then permuting. That way permutations happen on items returned by the same fixer type.
*/
@NotNull
public SuggestionList wrapPermuteFixedAligned(@Nullable SuggestionList prefixes, @Nullable SuggestionList suffixes, Suggestion.Fixer... fixers) {
SuggestionList wrappedList = new SuggestionList(project);
if (prefixes != null && !prefixes.isEmpty() && suffixes != null && !suffixes.isEmpty()) {
for (Suggestion.Fixer fixer : fixers) {
SuggestionList fixedPrefixes = prefixes.batchFixers(fixer);
SuggestionList fixedSuffixes = suffixes.batchFixers(fixer);
wrappedList.add(wrapPermute(fixedPrefixes, fixedSuffixes));
}
} else if (suffixes != null && !suffixes.isEmpty()) {
for (Suggestion.Fixer fixer : fixers) {
SuggestionList fixedSuffixes = suffixes.batchFixers(fixer);
wrappedList.add(wrapPermute(null, fixedSuffixes));
}
} else if (prefixes != null && !prefixes.isEmpty()) {
for (Suggestion.Fixer fixer : fixers) {
SuggestionList fixedPrefixes = prefixes.batchFixers(fixer);
wrappedList.add(wrapPermute(fixedPrefixes, null));
}
}
return wrappedList;
}
@Nullable
public Project getProject() {
return project;
}
@NotNull
public String get(int i) {
Suggestion suggestion = suggestions.get(i);
return suggestion != null ? suggestion.getText() : "";
}
}