All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.util.merge.Config Maven / Gradle / Ivy

Go to download

IBM Data Merge Utility - a template based transformation and enrichment engine

The newest version!
/*
 * 
 * Copyright 2015-2017 IBM
 * 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 com.ibm.util.merge;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import org.apache.commons.io.IOUtils;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.ibm.util.merge.data.DataElement;
import com.ibm.util.merge.data.DataObject;
import com.ibm.util.merge.data.DataPrimitive;
import com.ibm.util.merge.data.parser.DataProxyJson;
import com.ibm.util.merge.data.parser.Parsers;
import com.ibm.util.merge.exception.Merge500;
import com.ibm.util.merge.exception.MergeException;
import com.ibm.util.merge.template.Template;
import com.ibm.util.merge.template.content.Segment;
import com.ibm.util.merge.template.directive.Enrich;
import com.ibm.util.merge.template.directive.Insert;
import com.ibm.util.merge.template.directive.ParseData;
import com.ibm.util.merge.template.directive.Replace;
import com.ibm.util.merge.template.directive.SaveFile;
import com.ibm.util.merge.template.directive.enrich.provider.ProviderInterface;
import com.ibm.util.merge.template.directive.enrich.provider.ProviderMeta;
import com.ibm.util.merge.template.directive.enrich.provider.Providers;

/**
 * Provides configuration information for the Merge Utility -  
 * Implemented as a singleton with static convenience methods
 *
 * 

All configuration constructor values accept a JSON string. * This string only needs to provide values when you want to override a default.

*

* Both the Default Providers and Parsers lists must be complete, providing any * value removes all default entries. If you add a custom provider, you will need to * list all of the default providers you want as well as your new provider.

*

Configuration Format JSON

 * {
 * 	"nestLimit": n,
 * 	"insertLimit": n,
 * 	"tempFolder": "folder",
 *  "prettyJson" : "true",
 * 	"logLevel": "CRITICAL | SEVERE | WARN | INFO",
 * 	"envVars" : {"var":"value"},
 *	"defaultProviders" : ["providerClass","providerClass"],
 *	"defaultParsers" : ["parserClass","parserClass"],		
 * }
 * 
* * @author Mike Storey * @since: v4.0.0.B1 */ public class Config { private final String version = "4.0.0.B1"; private int nestLimit = 2; private int insertLimit = 20; private String tempFolder = "/opt/ibm/idmu/v4/archives"; private String loadFolder = "/opt/ibm/idmu/v4/packages"; private String logLevel = "SEVERE"; private boolean prettyJson = true; private HashMap envVars = new HashMap(); private String[] defaultProviders = { "com.ibm.util.merge.template.directive.enrich.provider.CacheProvider", "com.ibm.util.merge.template.directive.enrich.provider.CloudantProvider", "com.ibm.util.merge.template.directive.enrich.provider.FileSystemProvider", "com.ibm.util.merge.template.directive.enrich.provider.JdbcProvider", "com.ibm.util.merge.template.directive.enrich.provider.JndiProvider", "com.ibm.util.merge.template.directive.enrich.provider.MongoProvider", "com.ibm.util.merge.template.directive.enrich.provider.RestProvider", "com.ibm.util.merge.template.directive.enrich.provider.StubProvider" }; private String[] defaultParsers = { "com.ibm.util.merge.data.parser.DataProxyCsv", "com.ibm.util.merge.data.parser.DataProxyJson", "com.ibm.util.merge.data.parser.DataProxyXmlStrict" }; /* * Transient Values - Providers, Parsers and a JSON Proxy */ private transient Providers providers = new Providers(); private transient Parsers proxies = new Parsers(); private transient static final DataProxyJson proxy = new DataProxyJson(false); /** * Provide a default configuration. If the enviornment variable * idmu-config exists it is parsed as a json configuration value. * If the config environment variable does not exist, all defaults * are provided. * * @throws MergeException on Processing Errors */ public Config() throws MergeException { String configString = ""; try { configString = this.getEnv("idmu-config"); } catch (Throwable e) { // ignore } Logger rootLogger = LogManager.getLogManager().getLogger(""); rootLogger.setLevel(Level.parse(this.logLevel)); loadConfig(configString); } /** * Get a configuration from the provided environment variable name. * * @param configString The configuration JSON * @throws MergeException on Processing Errors */ public Config(String configString) throws MergeException { Logger rootLogger = LogManager.getLogManager().getLogger(""); rootLogger.setLevel(Level.parse(this.logLevel)); loadConfig(configString); } /** * Read a configuration from a config file * * @param configFile The configuration file * @throws MergeException on Processing Errors */ public Config(File configFile) throws MergeException { String configString; try { configString = new String(Files.readAllBytes(configFile.toPath()), "ISO-8859-1"); } catch (UnsupportedEncodingException e) { throw new Merge500("Unsupported Encoding Exception reading config file: " + configFile.toString() + " Message: "+ e.getMessage()); } catch (IOException e) { throw new Merge500("IO Exception reading config file: " + configFile.toString() + " Message: " + e.getMessage()); } Logger rootLogger = LogManager.getLogManager().getLogger(""); rootLogger.setLevel(Level.parse(this.logLevel)); loadConfig(configString); } /** * Read a configuration from an anonymous http source * * @param url The URL to fetch a config from * @throws MergeException on Processing Errors */ public Config(URL url) throws MergeException { String configString; try { configString = IOUtils.toString( new BufferedReader( new InputStreamReader( url.openStream()))); } catch (IOException e) { throw new Merge500("Unable to laod config " + url.toString()); } Logger rootLogger = LogManager.getLogManager().getLogger(""); rootLogger.setLevel(Level.parse(this.logLevel)); loadConfig(configString); } /** * Load the configuration provided * * @param configString The configuration JSON * @throws MergeException on Processing Errors */ private void loadConfig(String configString) throws MergeException { if (null != configString) { JsonElement ele = proxy.fromString(configString, JsonElement.class); if (null != ele && ele.isJsonObject()) { JsonObject me = ele.getAsJsonObject(); this.nestLimit = this.getIf(me, "nestLimit", this.nestLimit); this.insertLimit = this.getIf(me, "insertLimit", this.insertLimit); this.tempFolder = this.getIf(me, "tempFolder", this.tempFolder); this.loadFolder = this.getIf(me, "loadFolder", this.loadFolder); this.prettyJson = this.getIf(me, "prettyJson", true); this.logLevel = this.getIf(me, "logLevel", this.logLevel); if (me.has("envVars") && me.get("envVars").isJsonObject()) { this.envVars = new HashMap(); for (Entry var : me.get("envVars").getAsJsonObject().entrySet()) { this.envVars.put(var.getKey(), var.getValue().getAsString()); } } if (me.has("defaultProviders") && me.get("defaultProviders").isJsonArray()) { JsonArray list = me.get("defaultProviders").getAsJsonArray(); this.defaultProviders = new String[list.size()]; for (int i = 0; i < list.size(); i++ ) { this.defaultProviders[i] = list.get(i).getAsString(); } } if (me.has("defaultParsers")) { JsonArray list = me.get("defaultParsers").getAsJsonArray(); this.defaultParsers = new String[list.size()]; for (int i = 0; i < list.size(); i++ ) { this.defaultParsers[i] = list.get(i).getAsString(); } } } } this.registerDefaultProxies(); this.registerDefaultProviders(); Logger rootLogger = LogManager.getLogManager().getLogger(""); rootLogger.setLevel(Level.parse(this.logLevel)); } private int getIf(JsonObject me, String name, int value) { if (me.has(name)) { return me.get(name).getAsInt(); } else { return value; } } private String getIf(JsonObject object, String name, String value) { if (object.has(name)) { return object.get(name).getAsString(); } else { return value; } } private Boolean getIf(JsonObject object, String name, Boolean value) { if (object.has(name)) { return object.get(name).getAsBoolean(); } else { return value; } } /** * Abstraction of Environment access. Will leverage an entry from the * local Environment hashmap property. Environment Variables prefixed with * "VCAP:" will be treated as entries in the VCAP_SERVICES environment variable. * * You can provide environment values by adding entries to the envVars hashMap * * @param name The environment variable * @return The environment value * @throws MergeException on Processing Errors */ public String getEnv(String name) throws MergeException { if (envVars.containsKey(name)) { return envVars.get(name); } if (name.startsWith("VCAP:")) { return getVcapEntry(name.substring(5)); } String value = System.getenv(name); if (null == value) { throw new Merge500("enviornment variable not found"); } return value; } /** * @param serviceName The VCAP Service Name to lookup * @return the VCAP entry * @throws MergeException on Processing Errors */ public String getVcapEntry(String serviceName) throws MergeException { String VCAP_SERVICES = this.getEnv("VCAP_SERVICES"); String value = ""; if (null == VCAP_SERVICES) { throw new Merge500("VCAP_SERVICES enviornment variable missing"); } try { DataElement vcap = proxy.fromString(VCAP_SERVICES, DataElement.class); value = proxy.toString(vcap.getAsObject().get(serviceName).getAsList().get(0).getAsPrimitive()); } catch (Exception e) { throw new Merge500("VCAP_SERVICES contains malformed JSON or is missing service " + serviceName); } return value; } // // Simple Getters below here // public Boolean isPrettyJson() { return prettyJson; } public String getTempFolder() { return tempFolder; } public String getLoadFolder() { return loadFolder; } public int getNestLimit() { return nestLimit; } public int getInsertLimit() { return insertLimit; } public String getVersion() { return version; } // Parser Management public void registerDefaultProxies() throws MergeException { this.proxies.registerDefaultProxies(this.defaultParsers); } public DataElement parseString(int parseAs, String value) throws MergeException { return this.proxies.parseString(parseAs, value); } // Provider Management public ProviderInterface getProviderInstance(String className, String source, String parameter) throws MergeException { return this.providers.getProviderInstance(className, source, parameter); } public void registerDefaultProviders() throws MergeException { this.providers.registerDefaultProviders(this.defaultProviders); } /* * Constants and Options */ public static final int PARSE_NONE = 4; public static final int PARSE_CSV = 1; public static final int PARSE_JSON = 3; public static final int PARSE_XML = 5; public static final HashMap PARSE_OPTIONS() { HashMap values = new HashMap(); values.put(PARSE_CSV, "csv"); values.put(PARSE_JSON, "json"); values.put(PARSE_NONE, "none"); values.put(PARSE_XML, "xml"); return values; } public static final HashMap> getOptions() { HashMap> options = new HashMap>(); options.put("Parse Formats", PARSE_OPTIONS()); return options; } /** * Build a configuration object and return the json * @return A json string of all configuration and template/directive options * @throws MergeException on build errors. */ public String get() throws MergeException { // Build the return object and Config values DataObject returnObject = new DataObject(); DataObject config = new DataObject(); config.put("version", new DataPrimitive(version)); config.put("nestLimit", new DataPrimitive(nestLimit)); config.put("insertLimit", new DataPrimitive(insertLimit)); config.put("tempFolder", new DataPrimitive(tempFolder)); config.put("logLevel", new DataPrimitive(logLevel)); config.put("prettyJson", new DataPrimitive(prettyJson)); DataObject env = new DataObject(); for (String key : envVars.keySet()) { env.put(key, new DataPrimitive(envVars.get(key))); } returnObject.put("config", config); // Build the Providers List DataObject providers = new DataObject(); for (String provider : this.providers.keySet()) { ProviderMeta meta = this.getProviderInstance(provider, "source", "parameters").getMetaInfo(); DataObject providerData = new DataObject(); providerData.put("optionName", new DataPrimitive(meta.optionName)); providerData.put("sourceJson", new DataPrimitive(meta.sourceEnv)); providerData.put("commandHelp", new DataPrimitive(meta.commandHelp)); providerData.put("parseHelp", new DataPrimitive(meta.parseHelp)); providerData.put("returnHelp", new DataPrimitive(meta.returnHelp)); providers.put(provider, providerData); } returnObject.put("providers", providers); // Build Parser List DataObject parsers = new DataObject(); for (Integer parser : this.proxies.keySet()) { parsers.put(Integer.toString(parser), new DataPrimitive(proxies.get(parser).getClass().getName())); } returnObject.put("parsers", parsers); // Build the Object Enum Options list returnObject.put("template", theOptions(Template.getOptions())); returnObject.put("encoding", theOptions(Segment.getOptions())); returnObject.put("enrich", theOptions(Enrich.getOptions())); returnObject.put("insert", theOptions(Insert.getOptions())); returnObject.put("parse", theOptions(ParseData.getOptions())); returnObject.put("replace", theOptions(Replace.getOptions())); returnObject.put("save", theOptions(SaveFile.getOptions())); return proxy.toString(returnObject); } /** * Helper for "get" method * @param values Options from an Object getOptions * @return the Options converted to a DataElement */ public DataElement theOptions(HashMap> values) { DataObject enums = new DataObject(); for (String name : values.keySet()) { DataObject options = new DataObject(); enums.put(name, options); for (Integer option : values.get(name).keySet()) { options.put(Integer.toString(option), new DataPrimitive(values.get(name).get(option))); } } return enums; } /** * Check if the parse as parser supported * @param parseAs the parse format * @return true if the parse format is supported */ public boolean hasParser(int parseAs) { return (this.proxies.containsKey(new Integer(parseAs))); } /** * Check if the provider is supported * @param key provider class * @return true if it's a supported provider */ public boolean hasProvider(String key) { return (this.providers.containsKey(key)); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy