blob: 705a65e338a05c96963cabe5c346997fd07a5926 [file] [log] [blame]
/*
* 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 org.apache.stanbol.enhancer.servicesapi.helper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.clerezza.rdf.core.serializedform.SupportedFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility Class with methods allowing to parse line based configurations formatted
* like:
* <code><pre>
* &lt;key1&gt;;&lt;parm1&gt;=&lt;value1&gt;,&lt;value2&gt;;&lt;parm2&gt;=&lt;value1&gt;...
* &lt;key2&gt;;&lt;state&gt
* &lt;key3&gt;;&lt;state&gt=true
* &lt;key4&gt;;&lt;parm1&gt;=&lt;value1&gt;;&lt;parm1&gt;=&lt;value2&gt;
* </pre></code>
* Rules:<ul>
* <li> keys MUST NOT be contained multiple times
* <li> lines with empty keys are ignored (this includes empty lines or
* lines that are <code>null</code>)
* <li> If parameter appear multiple time values are appended
* <li> empty parameter names are ignored
* <li> parameters MIST NOT start with '='
* </ul>
* <p>
* This is intended to be used to parse richer configurations form OSGI
* configuration files.
*
* @author Rupert Westenthaler
*
*/
public final class ConfigUtils {
private ConfigUtils(){/* Do not create instances of utility classes */}
private static Map<String,String> rdfExt2Formats;
static {
Map<String,String> m = new HashMap<String,String>();
m.put(null, SupportedFormat.RDF_XML); //default to rdf+xml
m.put("", SupportedFormat.RDF_XML); //no extension is also mapped to rdf+xml
m.put("rdf", SupportedFormat.RDF_XML);
m.put("xml", SupportedFormat.RDF_XML);
m.put("owl", SupportedFormat.RDF_XML);
m.put("rdfs", SupportedFormat.RDF_XML);
m.put("json", SupportedFormat.RDF_JSON);
m.put("nt", SupportedFormat.N_TRIPLE);
m.put("n3", SupportedFormat.N3);
m.put("ttl", SupportedFormat.TURTLE);
rdfExt2Formats = Collections.unmodifiableMap(m);
}
/**
* Guesses the RDF format based on the provided file extension. Parsing
* <code>null</code> will return the default format.
* @param extension the extension or <code>null</code> to ask for the default
* @return the mime type or <code>null</code> if the parsed extension is not
* known.
*/
public static String guessRdfFormat(String extension){
return rdfExt2Formats.get(extension);
}
private static final Logger log = LoggerFactory.getLogger(ConfigUtils.class);
/**
* Parses configurations formatted like
* <code><pre>
* &lt;key1&gt;;&lt;parm1&gt;=&lt;value1&gt;,&lt;value2&gt;;&lt;parm2&gt;=&lt;value1&gt;...
* &lt;key2&gt;;&lt;state&gt
* &lt;key3&gt;;&lt;state&gt=true
* &lt;key4&gt;;&lt;parm1&gt;=&lt;value1&gt;;&lt;parm1&gt;=&lt;value2&gt;
* </pre></code>
* Rules:<ul>
* <li> keys MUST NOT be contained multiple times
* <li> lines with empty keys are ignored (this includes empty lines or
* lines that are <code>null</code>)
* <li> If parameter appear multiple time values are appended
* <li> empty parameter names are ignored
* <li> parameters MIST NOT start with '='
* </ul>
* @param configuration The configuration
* @throws IllegalArgumentException on any syntax error in the parsed
* configuration
*/
public static Map<String,Map<String,List<String>>> parseConfig(Iterable<String> configuration) {
Map<String,Map<String,List<String>>> config = new HashMap<String,Map<String,List<String>>>();
for(String line : configuration){
parseLine(config, line);
}
return config;
}
/**
* Parses configurations formatted like
* <code><pre>
* &lt;key1&gt;;&lt;parm1&gt;=&lt;value1&gt;,&lt;value2&gt;;&lt;parm2&gt;=&lt;value1&gt;...
* &lt;key2&gt;;&lt;state&gt
* &lt;key3&gt;;&lt;state&gt=true
* &lt;key4&gt;;&lt;parm1&gt;=&lt;value1&gt;;&lt;parm1&gt;=&lt;value2&gt;
* </pre></code>
* Rules:<ul>
* <li> keys MUST NOT be contained multiple times
* <li> lines with empty keys are ignored (this includes empty lines or
* lines that are <code>null</code>)
* <li> If parameter appear multiple time values are appended
* <li> empty parameter names are ignored
* <li> parameters MIST NOT start with '='
* </ul>
* @param confIterator The Iterator over the lines of the configuration.
* @throws IllegalArgumentException on any syntax error in the parsed
* configuration
*/
public static Map<String,Map<String,List<String>>> parseConfig(Iterator<String> confIterator) {
Map<String,Map<String,List<String>>> config = new HashMap<String,Map<String,List<String>>>();
while(confIterator.hasNext()){
parseLine(config, confIterator.next());
}
return config;
}
/**
* Returns the "key, parameter" entry parsed form the parsed configuration
* line.<p>
* This method is useful if the caller need to preserve the oder of multi
* line configurations and therefore can not use the parseConfig methods.
* @param line a configuration line
* @return the key, parameter entry
*/
public static Entry<String,Map<String,List<String>>> parseConfigEntry(String line){
String[] elements = line.split(";");
return Collections.singletonMap(elements[0].trim(), getParameters(elements,1))
.entrySet().iterator().next();
}
/**
* Internally used to parse single lines of an parsed {@link Iterable} or
* {@link Iterator}
* @param config the map used to write the parsed values
* @param line the line to parse
*/
private static void parseLine(Map<String,Map<String,List<String>>> config, String line) {
if(line == null || line.isEmpty() || line.charAt(0) == ';'){
log.warn("Configuration entry ignored because of empty Engine name " +
"(entry: '"+line+"')!");
}
String[] elements = line.split(";");
String key = elements[0].trim();
if(!config.containsKey(key)){
config.put(key, getParameters(elements,1));
} else {
throw new IllegalArgumentException("The configuration MUST NOT contain the same key '"+
elements[0]+"' multiple times!");
}
}
/**
* Parses the boolean value form the values for the parsed key.
* The state is assumed as <code>true</code> if the key is present and the
* value is either an empty list of the first element of the list evaluates
* to <code>{@link Boolean#parseBoolean(String)} == true</code>.
* @param parameters the parameter
* @param key the key
* @return the boolean state of the requested key
*/
public static boolean getState(Map<String,List<String>> parameters, String key){
List<String> value = parameters.get(key);
return value != null && (value.isEmpty() || Boolean.parseBoolean(
value.get(0)));
}
/**
* Getter for the first value of a given key
* @param parameters the parameters
* @param key the key
* @return the first value or <code>null</code> if the key is not present
* or the list is empty.
*/
public static String getValue(Map<String,List<String>> parameters, String key) {
List<String> values = parameters.get(key);
return values == null || values.isEmpty() ? null : values.get(1);
}
/**
* Utility that parses 'key=value,value2' parameters from the parsed array.
* If key appear multiple time values are appended.
* @param elements the elements
* @param start the start position within the parsed array to start parsing
* @return the parsed parameters. If no value is provided for a key the
* value of entries will be NOT <code>null</code> but en empty list. The
* returned Map provides read and write access.
* @throws IllegalArgumentExeption if elements are illegal formatted (e.g.
* if the start with an '='
*/
public static Map<String,List<String>> getParameters(String[] elements, int start) {
final Map<String,List<String>> parameters;
if(elements.length > start){
parameters = new HashMap<String,List<String>>(elements.length-start);
for(int i = start;i<elements.length;i++){
if(elements[i] != null && !elements[i].isEmpty()){
if(elements[i].charAt(0) == '='){
throw new IllegalArgumentException("Unable to " +
"parse parameters because element at index " +
i+" MUST NOT start with '=' (element: '"+
elements[i]+"')!");
}
int sepIndex = elements[i].indexOf('=');
String param = sepIndex > 0 ? elements[i].substring(0, sepIndex).trim() :
elements[i].trim();
String value = sepIndex > 0 && elements[i].length()> sepIndex+1 ?
elements[i].substring(sepIndex+1).trim() : null;
List<String> paramValues = parameters.get(param);
if(paramValues == null){
paramValues = new ArrayList<String>(3);
parameters.put(param, paramValues);
}
if(value != null){
for(String v : value.split(",")){
if(v != null){
paramValues.add(v);
}
}
}
}
}
} else {
parameters = Collections.emptyMap();
}
return parameters;
}
}