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

at.spardat.xma.datasource.RessourceBundleProviderServer Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     s IT Solutions AT Spardat GmbH - initial API and implementation
 *******************************************************************************/

// @(#) $Id: RessourceBundleProviderServer.java 2089 2007-11-28 13:56:13Z s3460 $
package at.spardat.xma.datasource;

import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.TreeMap;

import at.spardat.enterprise.exc.SysException;
import at.spardat.enterprise.util.DateUtil;
import at.spardat.enterprise.util.Types;
import at.spardat.xma.exception.Codes;
import at.spardat.xma.mdl.Atom;
import at.spardat.xma.session.XMASession;

/**
 * Provides tabular data from a RessourceBundle. The specification of these kind of data sources
 * must follow the syntax
 * 
 * type=rsc,bundle=at.spardat. ... .MyBundle
 * 
* i.e., the type must be the reserverd word rsc and a second attribute named * bundle indicates the name of the ressource bundle where the values are extracted * from.

* * The most typical usage are properties-files to implement ressource bundles. The following * paragraph defines how properties files are mapped to {@link TabularData} objects, which * are used from the XMA application to programmatically access the tabular data. We start * with an example. Suppose our table should have the following columns: *

 * column name         column type
 * ----------------------------------------
 * lastName            String
 * datBirth            Date
 * ynMarried           Boolean
 * betIncome           Numeric
 * 
* then a properties file providing the actual data looks like: *
 * COLS  = lastName,datBirth,ynMarried,betIncome
 * 10    = "Huber",D19720101,BY,N100000.23
 * 20    = "Maier",D19661110,BN,N20000.00
 * 50    = "Lilly",D20030101,B ,N
 * 
* * There must be one line with the key COLS that provides the name of the columns. * The remaining lines must have a numeric key that indicates the order of the lines (since * the lines in property files are unordered).

* * Each value (the part after the equal sign) contains the cells of the table rows, separated * by comma. String types are delimited with quotes. If the string value should contain a * quote, praefix it with double backslash (i.e., \\"). Date values start with a D and a date * followed in the ISO-format, i.e., YYYYMMDD. Booleans start with a B as type * sign, followed by Y or N. Numeric values start with N, followed * by a numeric string as defined by {@link java.lang.Double#parseDouble(java.lang.String)}.

* * Empty Strings must be specified via double quotes, i.e., quotes with no text in between. * All other empty types must start with the type character without following text, e.g., * N with no trailing text denotes an empty numeric.

* * If the provided table holds domain data, a property file must look like this: *

 * COLS  = COD_KEY,SHORT_VALUE,LONG_VALUE,VALID_FROM,VALID_TO
 * 10    = "ab",   "ab",       "abgetreten",D20030101,D20030720
 * 20    = "we",   "we",       "weggetreten",D20030101,D20030719
 * 
* * @author YSD, 19.06.2003 23:49:38 */ public class RessourceBundleProviderServer implements ITableProvider { /** * @see at.spardat.xma.datasource.ITableProvider#provideTable(at.spardat.xma.session.XMASession, at.spardat.xma.datasource.TableSpec, long) */ public ProviderResultServer provideTable (XMASession session, TableSpec spec, long lastModified) { String bundleString = spec.getProperty("bundle"); Locale l = spec.getLocale(); if (bundleString == null) { throw new SysException ("RessourceBundle spec " + spec.toString() + " misses bundle=...") .setCode (Codes.DS_MISSING_BUNDLE_ATTRIBUTE); } ResourceBundle bundle = ResourceBundle.getBundle (bundleString, l); TabularData table; TreeMap rankLineMap = new TreeMap(); // keys are Integers, values are Strings String columns = null; Enumeration keys = bundle.getKeys(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); String value = bundle.getString(key); if (value == null) continue; if (key.equals("COLS")) columns = value; else rankLineMap.put(new Integer(key), value); } if (columns == null) { throw new SysException ("RessourceBundle " + spec.toString() + ", missing line 'COLS=...' that defines the columns.") .setCode(Codes.DS_RSC_MISSING_HEADER); } /** * Check if the table is a domain table */ StringTokenizer tokizer = new StringTokenizer (columns, ","); ArrayList colList = new ArrayList(); while (tokizer.hasMoreTokens()) { colList.add(((String)tokizer.nextToken()).trim()); } String [] colListAsArray = new String[colList.size()]; colList.toArray(colListAsArray); if (TabularDomData.isDomainColStructure(colListAsArray)) { // create TabularDomData table = new TabularDomData(); } else { // create TabularData table = new TabularData(); } /** * Add columns to the TabularData */ for (int i = 0; i < colListAsArray.length; i++) { table.addColumn (colListAsArray[i]); } /** * For each entry in rankLineMap, add a TableRow to the table */ Iterator iter = rankLineMap.values().iterator(); while (iter.hasNext()) { String element = (String) iter.next(); addLine (table, element, spec); } ProviderResultServer result = new ProviderResultServer(); result.table_ = table; return result; } /** * adds a line to the table */ private void addLine (TabularData table, String line, TableSpec spec) { try { StreamTokenizer toki = getTokenizerFor (line); TabularDataRow row = new TabularDataRow (table); while (toki.nextToken() != StreamTokenizer.TT_EOF) { // System.out.println("token: " + toki.ttype); // System.out.println("string: " + toki.sval); if (toki.ttype == '"' || toki.ttype == StreamTokenizer.TT_WORD) { if (toki.ttype == '"') { if (toki.sval.length() == 0) row.add(Atom.EMPTY_STRING); else row.add(new Atom(toki.sval)); } else { // got some type which is not a string char type = toki.sval.charAt(0); int sLen = toki.sval.length(); switch (type) { case 'B': if (sLen == 1) row.add(Atom.EMPTY_BOOLEAN); else row.add (new Atom(toki.sval.length() >= 2 && toki.sval.charAt(1) == 'Y')); break; case 'D': if (sLen == 1) row.add(Atom.EMPTY_DATE); else { String date = toki.sval.substring(1); if (date.length() != 8) lineError ("invalid date "+date, line, spec); if (!DateUtil.isValid(date)) lineError ("invalid date "+date, line, spec); row.add (new Atom(Types.T_DATE, DateUtil.internal2Gregorian(date).getTime())); } break; case 'N': if (sLen == 1) row.add(Atom.EMPTY_BCD); else { double d = 0.0; try { d = Double.parseDouble(toki.sval.substring(1)); } catch (Exception ex) { lineError ("invalid numeric " + toki.sval, line, spec); } row.add(new Atom(d)); } break; default: lineError ("unknown type " + type, line, spec); } } toki.nextToken(); if (toki.ttype == StreamTokenizer.TT_EOF) break; if (toki.ttype != ',') lineError ("missing comma", line, spec); } else if (toki.ttype == ',') { row.add(Atom.EMPTY_STRING); } else { lineError ("wrong syntax", line, spec); } } table.addRow(row); } catch (IOException ex) { throw new SysException (ex, "unknown line " + line + ", tabular data source: " + spec.toString()) .setCode(Codes.DS_RSC_INVALID_LINE); } } /** * Throws an SysException indicating a syntax error */ private void lineError (String reason, String line, TableSpec spec) { throw new SysException ("data source: " + spec.toString() + ", line: " + line + ", " + reason) .setCode(Codes.DS_RSC_INVALID_LINE); } private static StreamTokenizer getTokenizerFor (String toParse) { StreamTokenizer toki = new StreamTokenizer (new StringReader (toParse)); toki.wordChars('a', 'z'); toki.wordChars('A', 'Z'); toki.wordChars('0', '9'); toki.wordChars('.', '.'); toki.wordChars('-', '-'); toki.wordChars('+', '+'); toki.wordChars(128 + 32, 255); toki.whitespaceChars(0, ' '); toki.quoteChar('"'); return toki; } /** * Returns 30 days, which de facto means never. However, it requires that some application id * is included in the cache keys to ignore cached resources if a new version is deployed * at the server. * * @see at.spardat.xma.datasource.ITableProvider#getExpireDurationClientSecs(java.lang.String) */ public int getExpireDurationClientSecs(String type) { return 3600*24*30; // 30 days } /** * Returns 30 days, which de facto means never. As long as the application is running, * the bundle cannot change. * * @see at.spardat.xma.datasource.ITableProvider#getExpireDurationServerSecs(java.lang.String) */ public int getExpireDurationServerSecs(String type) { return 3600*24*30; // 30 days } // public static void main(String[] args) throws Exception { // RessourceBundleProviderServer rp = new RessourceBundleProviderServer(); // TableSpec spec = new TableSpec ("type=rsc,bundle=at.spardat.xma.datasource.test,_loc=de_AT"); // ProviderResultServer result = rp.provideTable(spec, TabularDataSourceServer.UNKNOWN_TIMESTAMP); // TabularData data = (TabularData) result.table_; // //data.save(new File("c:/tmp/xx.txt")); // { // ITabularDomData domData = (ITabularDomData) data; // for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy