/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.grammars.visitors;
import static org.whole.lang.grammars.reflect.GrammarsEntityDescriptorEnum.As;
import static org.whole.lang.grammars.reflect.GrammarsEntityDescriptorEnum.Grammar;
import static org.whole.lang.grammars.reflect.GrammarsEntityDescriptorEnum.Name;
import static org.whole.lang.grammars.reflect.GrammarsEntityDescriptorEnum.NonTerminal;
import static org.whole.lang.grammars.reflect.GrammarsEntityDescriptorEnum.Production;
import static org.whole.lang.grammars.reflect.GrammarsFeatureDescriptorEnum.name;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.whole.lang.grammars.model.Grammar;
import org.whole.lang.grammars.model.Name;
import org.whole.lang.grammars.model.NonTerminal;
import org.whole.lang.grammars.model.Production;
import org.whole.lang.grammars.util.GrammarsUtils;
import org.whole.lang.iterators.AbstractPatternFilterIterator;
import org.whole.lang.iterators.IteratorFactory;
import org.whole.lang.matchers.Matcher;
import org.whole.lang.model.IEntity;
import org.whole.lang.model.adapters.IEntityAdapter;
import org.whole.lang.operations.ContentAssistOperation;
import org.whole.lang.queries.factories.QueriesEntityFactory;
import org.whole.lang.queries.model.KindTestEnum;
import org.whole.lang.queries.model.Path;
import org.whole.lang.reflect.EntityDescriptor;
import org.whole.lang.reflect.FeatureDescriptor;
import org.whole.lang.reflect.ILanguageKit;
import org.whole.lang.reflect.ReflectionFactory;
import org.whole.lang.util.BehaviorUtils;
import org.whole.lang.util.EntityUtils;
/**
* @author Riccardo Solmi, Enrico Persiani
*/
public class GrammarsContentAssistVisitor extends GrammarsIdentityVisitor {
public ContentAssistOperation getOperation() {
return (ContentAssistOperation) super.getOperation();
}
protected IEntity getSelectedEntity() {
return getOperation().getSelectedEntity();
}
public static Set<String> calculateNonTerminalValues(IEntity e) {
Grammar grammar = Matcher.findAncestor(Grammar, e);
if (grammar != null) {
Set<String> names = new HashSet<String>();
IEntity parent = e.wGetParent();
ILanguageKit languageKit = getLanguageKitIfExists(grammar);
if (languageKit != null) {
if (!grammar.getLexicalStructure().equals(parent.wGetParent()))
names.addAll(languageKit.getEntityDescriptorEnum().names());
if (!parent.wGetFeatureDescriptor(e).equals(name)) {
QueriesEntityFactory qef = QueriesEntityFactory.instance;
Path allTokenNames = qef.createPath(
qef.createSequence(
qef.createFeatureStep("lexicalStructure"),
qef.createFeatureStep("phraseStructure")),
qef.createChildStep(), qef.createFilter(
qef.createFeatureStep("name"),
qef.createKindTest(KindTestEnum.IMPL)));
for (NonTerminal nt : BehaviorUtils.<NonTerminal>compileAndLazyEvaluate(allTokenNames, grammar))
names.add(nt.getValue());
}
} else {
AbstractPatternFilterIterator<NonTerminal> i = IteratorFactory.<NonTerminal>descendantOrSelfMatcherIterator().withPattern(NonTerminal);
i.reset(grammar);
for (NonTerminal nt : i)
if (EntityUtils.isNotResolver(nt))
names.add(nt.getValue());
}
return names;
}
return Collections.emptySet();
}
public static Set<String> calculateAsNameValues(IEntity e) {
Grammar grammar = Matcher.findAncestor(Grammar, e);
if (grammar != null) {
Production production = Matcher.findAncestor(Production, e);
String entityName = production.getName().getValue();
ILanguageKit languageKit = getLanguageKitIfExists(grammar);
if (languageKit != null) {
EntityDescriptor<?> ed = languageKit.getEntityDescriptorEnum().valueOf(entityName);
if (ed != null) {
Set<String> names = new HashSet<String>();
for (FeatureDescriptor fd : ed.getEntityFeatureDescriptors())
names.add(fd.getName());
return names;
}
}
}
return Collections.emptySet();
}
public static ILanguageKit getLanguageKitIfExists(Grammar grammar) {
String languageURI = GrammarsUtils.getLanguageURI(grammar);
return ReflectionFactory.hasLanguageKit(languageURI, false, null) ?
ReflectionFactory.getLanguageKit(languageURI, false, null) : null;
}
@Override
public boolean visitAdapter(IEntityAdapter entity) {
if (Matcher.match(NonTerminal, entity))
getOperation().setResult(calculateNonTerminalValues(entity), NonTerminal);
else if (Matcher.match(Name, entity) && Matcher.match(As, entity.wGetParent()))
getOperation().setResult(calculateAsNameValues(entity), Name);
return false;
}
@Override
public void visit(NonTerminal entity) {
getOperation().setResult(calculateNonTerminalValues(entity), NonTerminal);
}
@Override
public void visit(Name entity) {
if (Matcher.match(As, entity.wGetParent()))
getOperation().setResult(calculateAsNameValues(entity), Name);
}
}