/*
* $Id$
*
* Copyright (C) 2003-2015 JNode.org
*
* This library 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 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.shell.syntax;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;
import org.jnode.plugin.ConfigurationElement;
import org.jnode.plugin.Extension;
import org.jnode.plugin.ExtensionPoint;
import org.jnode.plugin.ExtensionPointListener;
import org.jnode.shell.syntax.ArgumentSpecLoader.ArgumentSpec;
/**
* This syntax manager loads syntaxes specified using plugin extensions.
*
* @author crawley@jnode.org
*/
public class DefaultSyntaxManager implements SyntaxManager, ExtensionPointListener {
private final DefaultSyntaxManager parent;
private final HashMap<String, SyntaxBundle> syntaxes =
new HashMap<String, SyntaxBundle>();
private final HashMap<String, ArgumentSpec<?>[]> arguments =
new HashMap<String, ArgumentSpec<?>[]>();
private final ExtensionPoint syntaxEP;
/**
* Create a new instance
*/
public DefaultSyntaxManager(ExtensionPoint syntaxEP) {
this.parent = null;
this.syntaxEP = syntaxEP;
syntaxEP.addListener(this);
refreshSyntaxes();
}
private DefaultSyntaxManager(DefaultSyntaxManager parent) {
this.parent = parent;
this.syntaxEP = null;
if (parent == null) {
throw new IllegalArgumentException("parent cannot be null");
}
}
public void add(SyntaxBundle bundle) {
if (parent == null) {
throw new UnsupportedOperationException(
"Cannot modify the system syntax manager");
} else if (bundle != null) {
syntaxes.put(bundle.getAlias(), bundle);
}
}
public void add(String alias, ArgumentSpec<?>[] args) {
if (parent == null) {
throw new UnsupportedOperationException(
"Cannot modify the system syntax manager");
} else if (args != null) {
arguments.put(alias, args);
}
}
public SyntaxBundle remove(String alias) {
if (parent == null) {
throw new UnsupportedOperationException(
"Cannot modify the system syntax manager");
} else {
arguments.remove(alias);
return syntaxes.remove(alias);
}
}
public SyntaxBundle getSyntaxBundle(String alias) {
SyntaxBundle bundle = syntaxes.get(alias);
if (bundle != null) {
return bundle;
} else if (parent != null) {
return parent.getSyntaxBundle(alias);
} else {
return null;
}
}
public ArgumentBundle getArgumentBundle(String alias) {
ArgumentSpec<?>[] args = arguments.get(alias);
if (args != null) {
return makeArgumentBundle(args);
} else if (parent != null) {
return parent.getArgumentBundle(alias);
} else {
return null;
}
}
private ArgumentBundle makeArgumentBundle(ArgumentSpec<?>[] specs) {
Argument<?>[] args = new Argument<?>[specs.length];
for (int i = 0; i < specs.length; i++) {
try {
args[i] = specs[i].instantiate();
} catch (Exception e) {
return null;
}
}
return new ArgumentBundle(args);
}
public Collection<String> getKeys() {
Set<String> res = new HashSet<String>(syntaxes.size());
if (parent != null) {
res.addAll(parent.getKeys());
}
res.addAll(syntaxes.keySet());
return res;
}
public SyntaxManager createSyntaxManager() {
return new DefaultSyntaxManager(this);
}
/**
* Reload the syntax list from the extension-point
*/
protected void refreshSyntaxes() {
final Logger log = Logger.getLogger(getClass());
System.out.println("Refreshing syntax list");
if (syntaxEP != null) {
syntaxes.clear();
arguments.clear();
SyntaxSpecLoader syntaxLoader = new SyntaxSpecLoader();
ArgumentSpecLoader argumentLoader = new ArgumentSpecLoader();
for (Extension ext : syntaxEP.getExtensions()) {
for (ConfigurationElement element : ext.getConfigurationElements()) {
SyntaxSpecAdapter adaptedElement = new PluginSyntaxSpecAdapter(element);
try {
if (element.getName().equals("syntax")) {
SyntaxBundle bundle = syntaxLoader.loadSyntax(adaptedElement);
if (bundle != null) {
syntaxes.put(bundle.getAlias(), bundle);
}
} else if (element.getName().equals("argument-bundle")) {
ArgumentSpec<?>[] specs = argumentLoader.loadArguments(adaptedElement);
if (specs != null) {
arguments.put(element.getAttribute("alias"), specs);
}
} else {
throw new SyntaxFailureException("Element name is not 'syntax' or 'argument-bundle'");
}
} catch (Exception ex) {
log.log(Priority.WARN, "problem in syntax", ex);
}
}
}
}
}
public void extensionAdded(ExtensionPoint point, Extension extension) {
refreshSyntaxes();
}
public void extensionRemoved(ExtensionPoint point, Extension extension) {
refreshSyntaxes();
}
}