blob: 5b87db22a5fac61d6f20dfc2823fe7f5e8f20061 [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation.
*
* 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 org.apache.cocoon.components.modules.input;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.thread.ThreadSafe;
/**
*
* <h2>Configuration</h2>
* <table><tbody>
* <tr><th>input-module</th>
* <td>Configuration and name of input module used for the selection.</td>
* <td>req</td>
* <td>String</td><td><code>null</code></td>
* </tr>
* <tr><th>when</th>
* <td>Selection case, condition in test attribute, input module name
* in name attribute. Optional configuration as nested content.</td>
* <td>req</td><td>String</td><td><code>null</code></td>
* </tr>
* <tr><th>otherwise</th>
* <td>Default selection case. If not present and no case matches, <code>null</code>
* is returned.</td>
* <td></td><td>String</td><td><code>null</code></td>
* </tr>
* </tbody></table>
*
* @version $Id$
*/
public class SelectMetaInputModule extends AbstractMetaModule implements ThreadSafe {
private Map whenTest = null;
private ModuleHolder expression = null;
private ModuleHolder otherwise = null;
private String parameter = null;
public SelectMetaInputModule() {
super();
this.defaultInput = null; // not needed
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
*/
public void configure(Configuration config) throws ConfigurationException {
Configuration[] expr = config.getChildren("input-module");
if (expr == null || expr.length != 1) {
throw new ConfigurationException("Need to have exactly one input-module element.");
}
this.parameter = config.getChild("parameter").getValue();
Configuration[] whens = config.getChildren("when");
Configuration[] others = config.getChildren("otherwise");
if ((whens == null && others == null)
|| ((whens == null || whens.length == 0) && (others == null || others.length == 0))) {
throw new ConfigurationException("Need to have at least one when or otherwise element.");
}
if (others != null && others.length > 1) {
throw new ConfigurationException("Need to have at most one otherwise element.");
}
this.whenTest = new TreeMap();
for (int i = 0; i < expr.length; i++) {
String name = expr[i].getAttribute("name");
this.expression = new ModuleHolder(name, expr[i], null);
}
if (others != null) {
for (int i = 0; i < others.length; i++) {
String name = others[i].getAttribute("name");
this.otherwise = new ModuleHolder(name, others[i], null);
}
}
if (whens != null) {
for (int i = 0; i < whens.length; i++) {
String name = whens[i].getAttribute("name");
this.whenTest.put(
whens[i].getAttribute("test"),
new ModuleHolder(name, whens[i], null));
}
}
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.modules.input.InputModule#getAttribute(String, Configuration, Map)
*/
public Object getAttribute(String name, Configuration modeConf, Map objectModel)
throws ConfigurationException {
Object result = this.getAttribute(name, modeConf, objectModel, false);
return result;
}
public Object[] getAttributeValues(String name, Configuration modeConf, Map objectModel)
throws ConfigurationException {
Object result = this.getAttribute(name, modeConf, objectModel, true);
return (result != null ? (Object[]) result : null );
}
private Object getAttribute(String name, Configuration modeConf, Map objectModel, boolean getValues)
throws ConfigurationException {
if (!this.initialized) {
this.lazy_initialize();
}
ModuleHolder expression = this.expression;
ModuleHolder otherwise = this.otherwise;
ModuleHolder module = null;
String parameter = this.parameter;
boolean needRelease = false;
boolean dynamicConfig = (modeConf != null && modeConf.getChildren().length > 0);
if (dynamicConfig) {
// clear all configured values so that they
// don't get mixed up
expression = null;
otherwise = null;
needRelease = true;
Configuration[] expr = modeConf.getChildren("input-module");
Configuration[] other = modeConf.getChildren("otherwise");
if (expr != null && expr.length == 1) {
expression = new ModuleHolder(expr[0].getAttribute("name"), expr[0]);
}
if (other != null && other.length == 1) {
otherwise = new ModuleHolder(other[0].getAttribute("name"), other[0]);
}
parameter = modeConf.getChild("parameter").getValue();
}
String value =
(String) this.getValue(parameter, objectModel, expression.input, expression.name, expression.config);
if (needRelease) {
this.releaseModule(expression.input);
}
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug(
(dynamicConfig ? "(dyn)" : "(static)")
+ " select ("
+ value
+ ") from "
+ expression.name
+ ":"
+ parameter);
}
if (dynamicConfig && value != null) {
Configuration[] whens = modeConf.getChildren("when");
if (whens != null && whens.length > 0) {
int i = 0;
boolean found = false;
while (!found && i < whens.length) {
if (whens[i].getAttribute("test").equals(value)) {
found = true;
break;
}
i++;
}
if (found) {
module = new ModuleHolder(whens[i].getAttribute("name"), whens[i]);
}
}
} else if (value != null) {
module = (ModuleHolder) this.whenTest.get(value);
}
if (module != null) {
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("found matching when : "+module.name);
}
} else {
module = otherwise;
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("using otherwise : "+module.name);
}
}
Object result;
if (getValues){
result = (module == null ? null : this.getValues(name, objectModel, module));
} else {
result = (module == null ? null : this.getValue(name, objectModel, module));
}
if (needRelease && module != null) {
this.releaseModule(module.input);
}
if (this.getLogger().isDebugEnabled()) {
this.getLogger().debug("Obtained value : "+result);
}
return result;
}
/* (non-Javadoc)
* @see org.apache.avalon.framework.activity.Disposable#dispose()
*/
public void dispose() {
this.releaseModule(this.expression.input);
this.expression = null;
if (this.otherwise != null) {
this.releaseModule(this.otherwise.input);
this.otherwise = null;
}
for (Iterator i = this.whenTest.values().iterator(); i.hasNext();) {
ModuleHolder holder = (ModuleHolder) i.next();
this.releaseModule(holder.input);
}
this.whenTest = null;
super.dispose();
}
/* (non-Javadoc)
* @see org.apache.cocoon.components.modules.input.AbstractMetaModule#lazy_initialize()
*/
public synchronized void lazy_initialize() {
if (this.initialized) {
return;
}
super.lazy_initialize();
if (this.expression != null) {
this.expression.input = this.obtainModule(this.expression.name);
}
if (this.otherwise != null){
this.otherwise.input = this.obtainModule(this.otherwise.name);
}
if (this.whenTest != null){
for (Iterator i = this.whenTest.values().iterator(); i.hasNext(); ){
ModuleHolder moduleHolder = (ModuleHolder) i.next();
moduleHolder.input = this.obtainModule(moduleHolder.name);
}
}
}
}