/**
* $Id: $
* $Date: $
*
*/
package org.xmlsh.sh.shell;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.xmlsh.core.CoreException;
import org.xmlsh.core.InvalidArgumentException;
import org.xmlsh.core.XValue;
import org.xmlsh.sh.module.IModule;
import org.xmlsh.util.NameValueMap;
import org.xmlsh.util.Util;
/*
* Modules are like namespaces.
* They map a prefix to a package (instead of a URI)
*
* Modules also have a list of default prefixes, (e.g. "xmlsh")
*/
public class Modules implements
Iterable<IModule>, Cloneable {
private static final Logger mLogger = LogManager.getLogger();
private NameValueMap<IModule> mModules;
private NameValueMap<String> mPrefixMap;
Modules() {
super();
mModules = new NameValueMap<>();
mPrefixMap = new NameValueMap<>();
}
private Modules(Modules that) {
this();
mLogger.entry(that);
mModules = that.mModules.clone();
mPrefixMap = that.mPrefixMap.clone();
mLogger.exit();
}
@Override
public Modules clone() {
mLogger.entry();
return mLogger.exit(new Modules(this));
}
/**
* @param shell
* TODO
* @param init
* @param init
* @throws IOException
* @throws CoreException
* @throws Exception
* @returns true if init was called
*
*/
public boolean importModule(Shell shell, String prefix, IModule mod,
List<XValue> init) throws IOException, CoreException {
mLogger.entry(shell, prefix, mod, init);
assert (mod != null);
if(mod == null) {
throw new InvalidArgumentException("Module is null: ");
}
boolean bInit = false;
if(!mModules.containsValue(mod)) {
mLogger.debug("Initializing a new module: {}", mod);
shell.pushModule(mod);
try {
mod.onInit(shell, init);
bInit = true;
IModule deleted = mModules.put(mod.getName(), mod);
/*
* THis isnt necessarily bad - it means a module name cant be fully
* resolved without loading it
* and that a module may be loaded and initialized many times - fixing
* that here doesnt sovle it
* as the same thing can happen byh other means, different threads,
* multiple paths to the same module etc.
*
* Ideally we would have a global module resolution module but that is
* not necessarily right
*/
if(deleted != null)
mLogger.info("Replaced module definition by name {}", deleted);
} catch (Exception e) {
Util.wrapCoreException("Unexpected exception in importModule", e);
} finally {
@SuppressWarnings("unused")
IModule pmod = shell.popModule();
}
}
if(prefix != null)
mPrefixMap.put(prefix, mod.getName()); // should chnage to UUID or UURI
return mLogger.exit(bInit);
}
public IModule getExistingModuleByIModule(IModule mod) {
mLogger.entry(mod);
return mModules.getByValue(mod);
}
public IModule getExistingModuleByName(String name) {
mLogger.entry(name);
return mLogger.exit(mModules.get(name));
}
@Override
public Iterator<IModule> iterator() {
return mModules.values().iterator();
}
public boolean moduleExistsByName(String name) {
return mModules.containsKey(name);
}
public IModule getExistingModuleByPrefix(String prefix) {
if(prefix == null)
return null;
mLogger.entry(prefix);
String name = mPrefixMap.get(prefix);
if(name != null)
return getExistingModuleByName(name);
else
return null;
}
// true if the module has any prefix mappings
public boolean hasAnyPrefixes(IModule mh) {
return mPrefixMap.containsValue(mh.getName());
}
public Collection<String> getPrefixesForModule(IModule hm) {
List<String> set = new ArrayList<>();
for(Entry<String, String> e : mPrefixMap.entrySet()) {
if(e.getValue().equals(hm.getName()))
set.add(e.getKey());
}
return set;
}
}
//
//
// Copyright (C) 2008-2014 David A. Lee.
//
// The contents of this file are subject to the "Simplified BSD License" (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.opensource.org/licenses/bsd-license.php
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the License for the specific language governing rights and limitations
// under the License.
//
// The Original Code is: all this file.
//
// The Initial Developer of the Original Code is David A. Lee
//
// Portions created by (your name) are Copyright (C) (your legal entity). All
// Rights Reserved.
//
// Contributor(s): none.
//