# HG changeset patch # User Sascha L. Teichmann # Date 1409835805 -7200 # Node ID 3bb1c62ad73238dc162f70f472121d0c3530cad8 # Parent a1ceacf15d3af3297e238622d48de488d4e88386 Moved package org.dive4elements.river.utils to org.dive4elements.river.backend.utils. diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/backend/utils/DBCPConnectionProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backend/src/main/java/org/dive4elements/river/backend/utils/DBCPConnectionProvider.java Thu Sep 04 15:03:25 2014 +0200 @@ -0,0 +1,261 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +/* + * Copyright 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.dive4elements.river.backend.utils; + +import java.sql.Connection; +import java.sql.SQLException; + +import java.util.Iterator; +import java.util.Properties; +import java.util.Map; +import java.util.Collections; +import java.util.StringTokenizer; + +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.dbcp.BasicDataSourceFactory; + +import org.apache.log4j.Logger; + +import org.hibernate.HibernateException; + +import org.hibernate.connection.ConnectionProviderFactory; +import org.hibernate.connection.ConnectionProvider; + +import org.hibernate.cfg.Environment; + +/** + *

A connection provider that uses an Apache commons DBCP connection pool.

+ * + *

To use this connection provider set:
+ * hibernate.connection.provider_class org.hibernate.connection.DBCPConnectionProvider

+ * + *
Supported Hibernate properties:
+ *   hibernate.connection.driver_class
+ *   hibernate.connection.url
+ *   hibernate.connection.username
+ *   hibernate.connection.password
+ *   hibernate.connection.isolation
+ *   hibernate.connection.autocommit
+ *   hibernate.connection.pool_size
+ *   hibernate.connection (JDBC driver properties)
+ *
+ * All DBCP properties are also supported by using the hibernate.dbcp prefix. + * A complete list can be found on the DBCP configuration page: + * http://jakarta.apache.org/commons/dbcp/configuration.html. + *
+ *
Example:
+ *   hibernate.connection.provider_class org.hibernate.connection.DBCPConnectionProvider
+ *   hibernate.connection.driver_class org.hsqldb.jdbcDriver
+ *   hibernate.connection.username sa
+ *   hibernate.connection.password
+ *   hibernate.connection.url jdbc:hsqldb:test
+ *   hibernate.connection.pool_size 20
+ *   hibernate.dbcp.initialSize 10
+ *   hibernate.dbcp.maxWait 3000
+ *   hibernate.dbcp.validationQuery select 1 from dual
+ * + *

More information about configuring/using DBCP can be found on the + * DBCP website. + * There you will also find the DBCP wiki, mailing lists, issue tracking + * and other support facilities

+ * + * @see org.hibernate.connection.ConnectionProvider + * @author Dirk Verbeeck + */ +public class DBCPConnectionProvider +implements ConnectionProvider +{ + private static Logger log = Logger.getLogger(DBCPConnectionProvider.class); + + private static final String PREFIX = "hibernate.dbcp."; + + private BasicDataSource ds; + + // Old Environment property for backward-compatibility + // (property removed in Hibernate3) + private static final String DBCP_PS_MAXACTIVE = + "hibernate.dbcp.ps.maxActive"; + + // Property doesn't exists in Hibernate2 + private static final String AUTOCOMMIT = + "hibernate.connection.autocommit"; + + public void configure(Properties props) throws HibernateException { + try { + log.debug("Configure DBCPConnectionProvider"); + + // DBCP properties used to create the BasicDataSource + Properties dbcpProperties = new Properties(); + + // DriverClass & url + String jdbcDriverClass = props.getProperty(Environment.DRIVER); + String jdbcUrl = props.getProperty(Environment.URL); + dbcpProperties.put("driverClassName", jdbcDriverClass); + dbcpProperties.put("url", jdbcUrl); + + // Username / password + String username = props.getProperty(Environment.USER); + String password = props.getProperty(Environment.PASS); + dbcpProperties.put("username", username); + dbcpProperties.put("password", password); + + // Isolation level + String isolationLevel = props.getProperty(Environment.ISOLATION); + if (isolationLevel != null + && (isolationLevel = isolationLevel.trim()).length() > 0) { + dbcpProperties.put("defaultTransactionIsolation", isolationLevel); + } + + // Turn off autocommit (unless autocommit property is set) + String autocommit = props.getProperty(AUTOCOMMIT); + if (autocommit != null + && (autocommit = autocommit.trim()).length() > 0) { + dbcpProperties.put("defaultAutoCommit", autocommit); + } else { + dbcpProperties.put("defaultAutoCommit", String.valueOf(Boolean.FALSE)); + } + + // Pool size + String poolSize = props.getProperty(Environment.POOL_SIZE); + if (poolSize != null + && (poolSize = poolSize.trim()).length() > 0 + && Integer.parseInt(poolSize) > 0) { + dbcpProperties.put("maxActive", poolSize); + } + + // Copy all "driver" properties into "connectionProperties" + Properties driverProps = + ConnectionProviderFactory.getConnectionProperties(props); + + if (driverProps.size() > 0) { + StringBuilder connectionProperties = new StringBuilder(); + for (Iterator iter = driverProps.entrySet().iterator(); + iter.hasNext(); + ) { + Map.Entry entry = (Map.Entry)iter.next(); + String key = (String)entry.getKey(); + String value = (String)entry.getValue(); + connectionProperties + .append(key) + .append('=') + .append(value); + if (iter.hasNext()) { + connectionProperties.append(';'); + } + } + dbcpProperties.put( + "connectionProperties", connectionProperties.toString()); + } + + // Copy all DBCP properties removing the prefix + for (Iterator iter = props.entrySet().iterator() ; iter.hasNext() ;) { + Map.Entry entry = (Map.Entry)iter.next(); + String key = (String)entry.getKey(); + if (key.startsWith(PREFIX)) { + String property = key.substring(PREFIX.length()); + String value = (String)entry.getValue(); + dbcpProperties.put(property, value); + } + } + + // Backward-compatibility + if (props.getProperty(DBCP_PS_MAXACTIVE) != null) { + dbcpProperties.put( + "poolPreparedStatements", + String.valueOf(Boolean.TRUE)); + dbcpProperties.put( + "maxOpenPreparedStatements", + props.getProperty(DBCP_PS_MAXACTIVE)); + } + + // Some debug info + /* // commented out, because it leaks the password + if (log.isDebugEnabled()) { + log.debug("Creating a DBCP BasicDataSource" + + " with the following DBCP factory properties:"); + StringWriter sw = new StringWriter(); + dbcpProperties.list(new PrintWriter(sw, true)); + log.debug(sw.toString()); + } + */ + + // Let the factory create the pool + ds = (BasicDataSource)BasicDataSourceFactory + .createDataSource(dbcpProperties); + + // This needs to be done manually as it is somehow ignored + // by the BasicDataSourceFactory if you set it as a dbcpProperty + String connectionInitSqls = props.getProperty("connectionInitSqls"); + if (connectionInitSqls != null) { + StringTokenizer tokenizer = new StringTokenizer(connectionInitSqls, ";"); + ds.setConnectionInitSqls(Collections.list(tokenizer)); + } + // The BasicDataSource has lazy initialization + // borrowing a connection will start the DataSource + // and make sure it is configured correctly. + + // Connection conn = ds.getConnection(); + // conn.close(); + } + catch (Exception e) { + String message = "Could not create a DBCP pool"; + log.fatal(message, e); + if (ds != null) { + BasicDataSource x = ds; ds = null; + try { + x.close(); + } + catch (SQLException sqle) { + } + } + throw new HibernateException(message, e); + } + log.debug("Configure DBCPConnectionProvider complete"); + } + + public Connection getConnection() throws SQLException { + return ds.getConnection(); + } + + public void closeConnection(Connection conn) throws SQLException { + conn.close(); + } + + public void close() throws HibernateException { + try { + if (ds != null) { + BasicDataSource x = ds; ds = null; + x.close(); + } + } + catch (SQLException sqle) { + throw new HibernateException("Could not close DBCP pool", sqle); + } + } + + public boolean supportsAggressiveRelease() { + return false; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/backend/utils/DateGuesser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backend/src/main/java/org/dive4elements/river/backend/utils/DateGuesser.java Thu Sep 04 15:03:25 2014 +0200 @@ -0,0 +1,266 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.backend.utils; + +import java.util.Date; +import java.util.Calendar; + +import java.util.regex.Pattern; +import java.util.regex.Matcher; + +public final class DateGuesser { + public static final String [] MONTH = { + "jan", "feb", "mrz", "apr", "mai", "jun", + "jul", "aug", "sep", "okt", "nov", "dez" + }; + + public static final int guessMonth(String s) { + s = s.toLowerCase(); + for (int i = 0; i < MONTH.length; ++i) + if (MONTH[i].equals(s)) { + return i; + } + return -1; + } + + public static final Pattern YYYY_MM_DD = + Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})$"); + + public static final Pattern DD_MM_YYYY = + Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})$"); + + public static final Pattern MMM_YYYY = + Pattern.compile("^(\\d{0,2})\\.?(\\w{3})\\.?(\\d{2,4})$"); + + public static final Pattern GARBAGE_YYYY = + Pattern.compile("^\\D*(\\d{2,4})$"); + + public static final Pattern YYYY_MM_DDThh_mm = + Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})$"); + + public static final Pattern YYYY_MM_DDThh_mm_ss = + Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})$"); + + public static final Pattern DD_MM_YYYYThh_mm = + Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})T(\\d{1,2}):(\\d{2})$"); + + public static final Pattern DD_MM_YYYYThh_mm_ss = + Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})T(\\d{1,2}):(\\d{2}):(\\d{2})$"); + + public static final Pattern DDMMYY = + Pattern.compile("^(\\d{2})(\\d{2})(\\d{2})$"); + + private DateGuesser() { + } + + public static final int calendarMonth(String month) { + return calendarMonth(Integer.parseInt(month)); + } + + public static final int calendarMonth(int month) { + return Math.max(Math.min(month-1, 11), 0); + } + + /** + * Guess date by trying all different patterns. + * Throws IllegalArgumentException if not able to guess. + * @param s The date to be guessed (e.g. 11.02.2001). + * @return the parsed Date. + */ + public static Date guessDate(String s) { + if (s == null || (s = s.trim()).length() == 0) { + throw new IllegalArgumentException(); + } + + Matcher m; + + m = YYYY_MM_DD.matcher(s); + + if (m.matches()) { + Calendar cal = Calendar.getInstance(); + String year = m.group(1); + String month = m.group(2); + String day = m.group(3); + cal.clear(); + cal.set( + Integer.parseInt(year), + calendarMonth(month), + Integer.parseInt(day), + 12, 0, 0); + return cal.getTime(); + } + + m = DD_MM_YYYY.matcher(s); + + if (m.matches()) { + Calendar cal = Calendar.getInstance(); + String year = m.group(3); + String month = m.group(2); + String day = m.group(1); + cal.clear(); + cal.set( + Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), + calendarMonth(month), + Integer.parseInt(day), + 12, 0, 0); + return cal.getTime(); + } + + m = MMM_YYYY.matcher(s); + + if (m.matches()) { + int month = guessMonth(m.group(2)); + if (month >= 0) { + Calendar cal = Calendar.getInstance(); + String year = m.group(3); + String day = m.group(1); + cal.clear(); + cal.set( + Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), + month, + day.length() == 0 ? 15 : Integer.parseInt(day), + 12, 0, 0); + return cal.getTime(); + } + } + + m = YYYY_MM_DDThh_mm.matcher(s); + + if (m.matches()) { + Calendar cal = Calendar.getInstance(); + String year = m.group(1); + String month = m.group(2); + String day = m.group(3); + String hour = m.group(4); + String minute = m.group(5); + cal.clear(); + cal.set( + Integer.parseInt(year), + calendarMonth(month), + Integer.parseInt(day), + Integer.parseInt(hour), + Integer.parseInt(minute), + 0 + ); + return cal.getTime(); + } + + m = YYYY_MM_DDThh_mm_ss.matcher(s); + + if (m.matches()) { + Calendar cal = Calendar.getInstance(); + String year = m.group(1); + String month = m.group(2); + String day = m.group(3); + String hour = m.group(4); + String minute = m.group(5); + String second = m.group(6); + cal.clear(); + cal.set( + Integer.parseInt(year), + calendarMonth(month), + Integer.parseInt(day), + Integer.parseInt(hour), + Integer.parseInt(minute), + Integer.parseInt(second) + ); + return cal.getTime(); + } + + m = DD_MM_YYYYThh_mm.matcher(s); + + if (m.matches()) { + Calendar cal = Calendar.getInstance(); + String year = m.group(3); + String month = m.group(2); + String day = m.group(1); + String hour = m.group(4); + String minute = m.group(5); + cal.clear(); + cal.set( + Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), + calendarMonth(month), + Integer.parseInt(day), + Integer.parseInt(hour), + Integer.parseInt(minute), + 0 + ); + return cal.getTime(); + } + + m = DD_MM_YYYYThh_mm_ss.matcher(s); + + if (m.matches()) { + Calendar cal = Calendar.getInstance(); + String year = m.group(3); + String month = m.group(2); + String day = m.group(1); + String hour = m.group(4); + String minute = m.group(5); + String second = m.group(6); + cal.clear(); + cal.set( + Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), + calendarMonth(month), + Integer.parseInt(day), + Integer.parseInt(hour), + Integer.parseInt(minute), + Integer.parseInt(second) + ); + return cal.getTime(); + } + + m = DDMMYY.matcher(s); + + if (m.matches()) { + Calendar cal = Calendar.getInstance(); + String day = m.group(1); + String month = m.group(2); + String yearS = m.group(3); + int year = Integer.parseInt(yearS); + + if (year <= cal.get(Calendar.YEAR) % 100) { + year += 2000; + } + else { + year += 1900; + } + cal.clear(); + cal.set( + year, + Integer.parseInt(month), // month + Integer.parseInt(day), // day + 12, 0, 0); + return cal.getTime(); + } + + m = GARBAGE_YYYY.matcher(s); + + if (m.matches()) { + Calendar cal = Calendar.getInstance(); + String year = m.group(1); + cal.clear(); + cal.set( + Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), + 5, // month + 15, // day + 12, 0, 0); + return cal.getTime(); + } + + throw new IllegalArgumentException(); + } + + public static void main(String [] args) { + for (int i = 0; i < args.length; ++i) { + System.out.println(args[i] + ": " + guessDate(args[i])); + } + } +} +// end of file diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/backend/utils/DateUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backend/src/main/java/org/dive4elements/river/backend/utils/DateUtil.java Thu Sep 04 15:03:25 2014 +0200 @@ -0,0 +1,37 @@ +/* Copyright (C) 2014 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.backend.utils; + +import java.util.Date; +import java.util.Calendar; + +public final class DateUtil { + + private DateUtil() { + } + + /** Create Date on first moment (1st jan) of given year. */ + public static Date getStartDateFromYear(int year) { + Calendar cal = Calendar.getInstance(); + cal.clear(); + cal.set(year, 0, 1, 0, 0, 0); + + return cal.getTime(); + } + + + /** Create Date on last moment (31st dec) of given year. */ + public static Date getEndDateFromYear(int year) { + Calendar cal = Calendar.getInstance(); + cal.clear(); + cal.set(year, 11, 31, 23, 59, 59); + + return cal.getTime(); + } +} diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/backend/utils/DouglasPeuker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backend/src/main/java/org/dive4elements/river/backend/utils/DouglasPeuker.java Thu Sep 04 15:03:25 2014 +0200 @@ -0,0 +1,81 @@ +package org.dive4elements.river.backend.utils; + +import org.dive4elements.river.importer.XY; // TODO: Move to a more common package. + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class DouglasPeuker +{ + public static final double EPSILON = 1e-4; + + private DouglasPeuker() { + } + + public static List simplify(List input) { + return simplify(input, EPSILON); + } + + public static List simplify(List input, double epsilon) { + + int N = input.size(); + + if (N < 3) { + return new ArrayList(input); + } + + List simplified = recursiveSimplify(input, 0, N-1, epsilon); + + List output = new ArrayList(simplified.size()+2); + output.add(input.get(0)); + output.addAll(simplified); + output.add(input.get(N-1)); + + return output; + } + + private static List recursiveSimplify( + List input, + int start, + int end, + double epsilon + ) { + XY a = input.get(start); + XY b = input.get(end); + + // Normal of hesse normal form. + XY n = new XY(b).sub(a).ortho().normalize(); + + // distance offset of the hesse normal form. + double d = n.lineOffset(a); + + double maxDist = -Double.MAX_VALUE; + int maxIdx = -1; + + for (int i = start+1; i < end; ++i) { + double dist = Math.abs(n.dot(input.get(i)) + d); + if (dist > maxDist) { + maxDist = dist; + maxIdx = i; + } + } + + if (maxDist < epsilon) { + // All points between a and b can be ignored. + return Collections.emptyList(); + } + + // Split by input[maxIdx]. + List before = recursiveSimplify(input, start, maxIdx, epsilon); + List after = recursiveSimplify(input, maxIdx, end, epsilon); + + List output = new ArrayList(before.size()+1+after.size()); + output.addAll(before); + output.add(input.get(maxIdx)); + output.addAll(after); + + return output; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/backend/utils/EpsilonComparator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backend/src/main/java/org/dive4elements/river/backend/utils/EpsilonComparator.java Thu Sep 04 15:03:25 2014 +0200 @@ -0,0 +1,36 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.backend.utils; + +import java.util.Comparator; +import java.io.Serializable; + +/** Comparator with some tolerance (epsilon). */ +public class EpsilonComparator implements Comparator, Serializable +{ + public static final double EPSILON = 1e-4; + + /** Ready-made comparator with 1e-4 tolerance. */ + public static final EpsilonComparator CMP = new EpsilonComparator(EPSILON); + + private double epsilon; + + public EpsilonComparator(double epsilon) { + this.epsilon = epsilon; + } + + @Override + public int compare(Double a, Double b) { + double diff = a - b; + if (diff < -epsilon) return -1; + if (diff > epsilon) return +1; + return 0; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/backend/utils/StringUtil.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/backend/src/main/java/org/dive4elements/river/backend/utils/StringUtil.java Thu Sep 04 15:03:25 2014 +0200 @@ -0,0 +1,828 @@ +/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde + * Software engineering by Intevation GmbH + * + * This file is Free Software under the GNU AGPL (>=v3) + * and comes with ABSOLUTELY NO WARRANTY! Check out the + * documentation coming with Dive4Elements River for details. + */ + +package org.dive4elements.river.backend.utils; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Locale; + +import java.net.URLEncoder; +import java.net.URLDecoder; + +import java.io.UnsupportedEncodingException; +import java.io.IOException; +import java.io.BufferedReader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.PrintWriter; + + +public final class StringUtil { + final static String NUMBER_SEPERATOR = ";"; + final static String LINE_SEPERATOR = ":"; + + private StringUtil() { + } + + public static final String double2DArrayToString(double[][] values) { + + if (values == null) { + throw new IllegalArgumentException("keine double[][]-Werte"); + } + + StringBuilder strbuf = new StringBuilder(); + + for (int i=0; i < values.length; i++) { + if (i>0) { + strbuf.append(LINE_SEPERATOR); + } + for (int j=0; j < values[i].length; j++) { + if (j > 0) { + strbuf.append(NUMBER_SEPERATOR); + } + strbuf.append(values[i][j]); + } + } + + return strbuf.toString(); + } + + public static final double[][] stringToDouble2DArray(String str) { + if (str == null || str.length() == 0) { + return null; + } + + String[] lineSplit = str.split(LINE_SEPERATOR); + double[][] array2D = new double[lineSplit.length][]; + for (int i=0; i < lineSplit.length; i++) { + String[] numberSplit = lineSplit[i].split(NUMBER_SEPERATOR); + + double[] numbers = new double[numberSplit.length]; + for (int j=0; j < numberSplit.length; j++) { + numbers[j] = Double.valueOf(numberSplit[j]).doubleValue(); + } + + array2D[i] = numbers; + } + + return array2D; + } + + /** + * Remove first occurrence of "[" and "]" (if both do occur). + * @param value String to be stripped of [] (might be null). + * @return input string but with [ and ] removed, or input string if no + * brackets were found. + */ + public static final String unbracket(String value) { + // null- guard + if (value == null) return value; + + int start = value.indexOf("["); + int end = value.indexOf("]"); + + if (start < 0 || end < 0) { + return value; + } + + value = value.substring(start + 1, end); + + return value; + } + + + /** + * From "Q=1" make "W(Q=1)". + * @return original string wraped in "W()" if it contains a "Q", original + * string otherwise. + */ + public static String wWrap(String wOrQ) { + return (wOrQ != null && wOrQ.indexOf("Q") >=0) + ? "W(" + wOrQ + ")" + : wOrQ; + } + + + public static final String [] splitLines(String s) { + if (s == null) { + return null; + } + ArrayList list = new ArrayList(); + + BufferedReader in = null; + + try { + in = + new BufferedReader( + new StringReader(s)); + + String line; + + while ((line = in.readLine()) != null) { + list.add(line); + } + } + catch (IOException ioe) { + return null; + } + finally { + if (in != null) + try { + in.close(); + } + catch (IOException ioe) {} + } + + return list.toArray(new String[list.size()]); + } + + public static final String concat(String [] s) { + return concat(s, null); + } + + public static final String concat(String [] s, String glue) { + if (s == null) { + return null; + } + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length; ++i) { + if (i > 0 && glue != null) { + sb.append(glue); + } + sb.append(s[i]); + } + return sb.toString(); + } + + public static final String [] splitAfter(String [] src, int N) { + if (src == null) { + return null; + } + + ArrayList list = new ArrayList(src.length); + for (int i = 0; i < src.length; ++i) { + String s = src[i]; + int R; + if (s == null || (R = s.length()) == 0) { + list.add(s); + } + else { + while (R > N) { + list.add(s.substring(0, N)); + s = s.substring(N); + R = s.length(); + } + list.add(s); + } + } + return list.toArray(new String[list.size()]); + } + + public static final String [] splitQuoted(String s) { + return splitQuoted(s, '"'); + } + + public static final String[] fitArray(String [] src, String [] dst) { + if (src == null) { + return dst; + } + if (dst == null) { + return src; + } + + if (src.length == dst.length) { + return src; + } + + System.arraycopy(src, 0, dst, 0, Math.min(dst.length, src.length)); + + return dst; + } + + public static final String [] splitQuoted(String s, char quoteChar) { + if (s == null) { + return null; + } + ArrayList l = new ArrayList(); + int mode = 0, last_mode = 0; + StringBuilder sb = new StringBuilder(); + for (int N = s.length(), i = 0; i < N; ++i) { + char c = s.charAt(i); + switch (mode) { + case 0: // unquoted mode + if (c == quoteChar) { + mode = 1; // to quoted mode + if (sb.length() > 0) { + l.add(sb.toString()); + sb.setLength(0); + } + } + else if (c == '\\') { + last_mode = 0; + mode = 2; // escape mode + } + else if (!Character.isWhitespace(c)) { + sb.append(c); + } + else if (sb.length() > 0) { + l.add(sb.toString()); + sb.setLength(0); + } + break; + case 1: // quote mode + if (c == '\\') { + last_mode = 1; + mode = 2; // escape mode + } + else if (c == quoteChar) { // leave quote mode + l.add(sb.toString()); + sb.setLength(0); + mode = 0; // to unquoted mode + } + else { + sb.append(c); + } + break; + case 2: // escape mode + sb.append(c); + mode = last_mode; + break; + } + } + if (sb.length() > 0) { + l.add(sb.toString()); + } + return l.toArray(new String[l.size()]); + } + + public static final String [] splitUnique(String s) { + return splitUnique(s, "[\\s,]+"); + } + + public static final String [] splitUnique(String s, String sep) { + return s != null ? unique(s.split(sep)) : null; + } + + public static final String [] unique(String [] str) { + if (str == null || str.length == 1) { + return str; + } + + Arrays.sort(str); + + for (int i = 1; i < str.length; ++i) + if (str[i].equals(str[i-1])) { + ArrayList list = new ArrayList(str.length); + + for (int j = 0; j < i; ++j) { + list.add(str[j]); + } + + String last = str[i]; + + for (++i; i < str.length; ++i) + if (!last.equals(str[i])) { + list.add(last = str[i]); + } + + return list.toArray(new String[list.size()]); + } + + return str; + } + + public static final String [] ensureEmptyExistence(String [] str) { + if (str == null) { + return null; + } + + for (int i = 0; i < str.length; ++i) + if (str[i].length() == 0) { + if (i != 0) { // copy to front + String t = str[0]; + str[0] = str[i]; + str[i] = t; + } + return str; + } + + String [] n = new String[str.length+1]; + n[0] = ""; + System.arraycopy(str, 0, n, 1, str.length); + return n; + } + + public static final String ensureWidthPadLeft(String s, int width, char pad) { + int N = s.length(); + if (N >= width) { + return s; + } + StringBuilder sb = new StringBuilder(width); + for (; N < width; ++N) { + sb.append(pad); + } + sb.append(s); + return sb.toString(); + } + + public static final String [] splitWhiteSpaceWithNAsPad( + String s, + int N, + String pad + ) { + if (s == null) { + return null; + } + + boolean copyChars = true; + int count = 0; // number of WS + + int S = s.length(); + + ArrayList parts = new ArrayList(); + + StringBuilder part = new StringBuilder(S); + + for (int i = 0; i < S; ++i) { + char c = s.charAt(i); + if (copyChars) { // char mode + if (Character.isWhitespace(c)) { + if (part.length() > 0) { + parts.add(part.toString()); + part.setLength(0); + } + count = 1; + copyChars = false; // to WS mode + } + else { + part.append(c); + } + } + else { // counting WS + if (Character.isWhitespace(c)) { + ++count; + } + else { + while (count >= N) {// enough to insert pad? + parts.add(pad); + count -= N; + } + part.append(c); + count = 0; + copyChars = true; // back to char mode + } + } + } // for all chars + + if (copyChars) { + if (part.length() > 0) { + parts.add(part.toString()); + } + } + else { + while (count >= N) { // enough to insert pad? + parts.add(pad); + count -= N; + } + } + + return parts.toArray(new String[parts.size()]); + } + + public static final String encodeURL(String url) { + try { + return url != null + ? URLEncoder.encode(url, "UTF-8") + : ""; + } + catch (UnsupportedEncodingException usee) { + throw new RuntimeException(usee.getLocalizedMessage()); + } + } + + public static final String decodeURL(String url) { + try { + return url != null + ? URLDecoder.decode(url, "UTF-8") + : ""; + } + catch (UnsupportedEncodingException usee) { + throw new RuntimeException(usee.getLocalizedMessage()); + } + } + + public static final boolean isEmpty(String s) { + return s == null || s.length() == 0; + } + + public static final String empty(String s) { + return s == null ? "" : s; + } + + + public static final String trim(String s) { + return s != null ? s.trim() : null; + } + + public static final String uniqueWhitespaces(String s) { + if (s == null) { + return null; + } + + boolean wasWS = false; + StringBuilder sb = new StringBuilder(); + + for (int N = s.length(), i = 0; i < N; ++i) { + char c = s.charAt(i); + if (Character.isWhitespace(c)) { + if (!wasWS) { + sb.append(c); + wasWS = true; + } + } + else { + sb.append(c); + wasWS = false; + } + } + + return sb.toString(); + } + + public static final String replaceNewlines(String s) { + return s == null + ? null + : s.replace('\r', ' ').replace('\n', ' '); + } + + /* + public static final String quoteReplacement(String s) { + + if (s == null || (s.indexOf('\\') == -1 && s.indexOf('$') == -1)) + return s; + + StringBuilder sb = new StringBuilder(); + + for (int N = s.length(), i = 0; i < N; ++i) { + char c = s.charAt(i); + if (c == '\\' || c == '$') sb.append('\\'); + sb.append(c); + } + + return sb.toString(); + } + */ + + public static final String quoteReplacement(String s) { + + if (s == null) { + return null; + } + + for (int N = s.length(), i = 0; i < N; ++i) { // plain check loop + char c = s.charAt(i); + if (c == '$' || c == '\\') { // first special -> StringBuilder + StringBuilder sb = new StringBuilder(s.substring(0, i)) + .append('\\') + .append(c); + for (++i; i < N; ++i) { // build StringBuilder with rest + if ((c = s.charAt(i)) == '$' || c == '\\') { + sb.append('\\'); + } + sb.append(c); + } + return sb.toString(); + } + } + + return s; + } + + public static final String repeat(String what, int times) { + return repeat(what, times, new StringBuilder()).toString(); + } + + public static final StringBuilder repeat(String what, int times, StringBuilder sb) { + while (times-- > 0) { + sb.append(what); + } + return sb; + } + + /** + * Returns the file name without extension. + */ + public static final String cutExtension(String s) { + if (s == null) { + return null; + } + int dot = s.lastIndexOf('.'); + return dot >= 0 + ? s.substring(0, dot) + : s; + } + + public static final String extension(String s) { + if (s == null) { + return null; + } + int dot = s.lastIndexOf('.'); + return dot >= 0 + ? s.substring(dot+1) + : s; + } + + public static final String [] splitExtension(String x) { + if (x == null) { + return null; + } + int i = x.lastIndexOf('.'); + return i < 0 + ? new String[] { x, null } + : new String[] { x.substring(0, Math.max(0, i)), x.substring(i+1).toLowerCase() }; + } + + public static String entityEncode(String s) { + if (s == null || s.length() == 0) { + return s; + } + + StringBuilder sb = new StringBuilder(); + for (int i=0, N =s.length(); i < N; i++) { + char c = s.charAt(i); + switch (c) { + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '&': + sb.append("&"); + break; + default: + sb.append(c); + } + } + return sb.toString(); + } + + public static String entityDecode(String s) { + if (s == null || s.length() == 0) { + return s; + } + + boolean amp = false; + StringBuilder sb = new StringBuilder(); + StringBuilder ampbuf = new StringBuilder(); + for (int i=0, N =s.length(); i < N; i++) { + char c = s.charAt(i); + if (amp) { + if (c == ';') { + amp = false; + String str = ampbuf.toString(); + ampbuf.setLength(0); + if (str.equals("lt")) { + sb.append('<'); + } + else if (str.equals("gt")) { + sb.append('>'); + } + else if (str.equals("amp")) { + sb.append('&'); + } + else { + sb.append('&').append(str).append(';'); + } + } + else { + ampbuf.append(c); + } + } + else if (c=='&') { + amp = true; + } + else { + sb.append(c); + } + + } + return sb.toString(); + } + + public static final String quote(String s) { + return quote(s, '"'); + } + + public static final String quote(String s, char quoteChar) { + if (s == null) { + return null; + } + + int N = s.length(); + + if (N == 0) + return new StringBuilder(2) + .append(quoteChar) + .append(quoteChar) + .toString(); + + StringBuilder sb = null; + + int i = 0; + + for (; i < N; ++i) { + char c = s.charAt(i); + + if (Character.isWhitespace(c)) { + sb = new StringBuilder() + .append(quoteChar) + .append(s.substring(0, i+1)); + break; + } + else if (c == quoteChar) { + sb = new StringBuilder() + .append(quoteChar) + .append(s.substring(0, i)) + .append('\\') + .append(quoteChar); + break; + } + } + + if (sb == null) { + return s; + } + + for (++i; i < N; ++i) { + char c = s.charAt(i); + if (c == quoteChar || c == '\\') { + sb.append('\\'); + } + + sb.append(c); + } + + return sb.append(quoteChar).toString(); + } + + /* + public static String sprintf(String format, Object... args) { + return sprintf(null, format, args); + } + */ + + public static String sprintf(Locale locale, String format, Object ... args) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.printf(locale, format, args); + pw.flush(); + return sw.toString(); + } + + + public static void testQuote() { + System.err.println("testing quote:"); + + String cases [] = { + "", "''", + "test", "test", + "test test", "'test test'", + " test", "' test'", + "test ", "'test '", + " test ", "' test '", + "'test", "'\\'test'", + "'", "'\\''", + " ' ' ", "' \\' \\' '", + "te'st", "'te\\'st'" + }; + + int failed = 0; + + for (int i = 0; i < cases.length; i += 2) { + String in = cases[i]; + String out = cases[i+1]; + + String res = quote(in, '\''); + if (!res.equals(out)) { + ++failed; + System.err.println( + "quote failed on: >" + in + + "< result: >" + res + + "< expected: >" + out + "<"); + } + } + + int T = cases.length/2; + + System.err.println("tests total: " + T); + System.err.println("tests failed: " + failed); + System.err.println("tests passed: " + (T - failed)); + } + + public static void testQuoteReplacement() { + System.err.println("testing quoteReplacement:"); + + String cases [] = { + "", "", + "test", "test", + "$", "\\$", + "\\", "\\\\", + "\\$", "\\\\\\$", + "test\\$", "test\\\\\\$", + "\\test", "\\\\test", + "test$", "test\\$", + "test$test", "test\\$test", + "$test$", "\\$test\\$" + }; + + int failed = 0; + + for (int i = 0; i < cases.length; i += 2) { + String in = cases[i]; + String out = cases[i+1]; + + String res = quoteReplacement(in); + if (!res.equals(out)) { + ++failed; + System.err.println( + "quoteReplacement failed on: '" + in + + "' result: '" + res + + "' expected: '" + out + "'"); + } + } + + int T = cases.length/2; + + System.err.println("tests total: " + T); + System.err.println("tests failed: " + failed); + System.err.println("tests passed: " + (T - failed)); + } + + public static void testStringArray2D() { + int total = 0; + int fail = 0; + int passed = 0; + + System.err.println("testing StringArray2D:"); + + double[][] testarray = {{1.0, 2.0, 3.0}, + {1.1, 2.1, 3.1}, + {100.2, 200.2} + }; + String str = double2DArrayToString(testarray); + + total += 1; + if (str.equals("1.0;2.0;3.0:1.1;2.1;3.1:100.2;200.2")) { + passed +=1; + } + else { + fail +=1; + System.err.println("Der Ergebnis-String ist nicht richtig:"); + System.err.println(str); + } + + + + double[][] testarray2 = stringToDouble2DArray(str); + boolean failed = false; + + total +=1; + for (int i=0; i < testarray.length; i++) + for (int j=0; j < testarray[i].length; j++) + if (testarray[i][j] != testarray2[i][j]) { + System.err.println("Test scheitert bei i=" +i +" j=" +j); + System.err.println("alter Wert=" + testarray[i][j] +" neuer Wert=" +testarray2[i][j]); + failed = true; + } + if (failed) { + fail +=1; + } + else { + passed +=1; + } + System.err.println("tests total: "+ total); + System.err.println("tests failed: "+ fail); + System.err.println("tests passed: "+ passed); + } + + public static void main(String [] args) { + + testQuoteReplacement(); + testQuote(); + testStringArray2D(); + } + + /** Check for occurence of needle in hay, converting both to lowercase + * to be ignorant of cases. */ + public static boolean containsIgnoreCase(String hay, String needle) { + return hay.toLowerCase().contains(needle.toLowerCase()); + } +} +// end of file diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/ImportRiver.java --- a/backend/src/main/java/org/dive4elements/river/importer/ImportRiver.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/ImportRiver.java Thu Sep 04 15:03:25 2014 +0200 @@ -41,7 +41,7 @@ import org.dive4elements.river.model.River; import org.dive4elements.river.model.Unit; -import org.dive4elements.river.utils.DouglasPeuker; +import org.dive4elements.river.backend.utils.DouglasPeuker; import java.io.File; import java.io.IOException; diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/Importer.java --- a/backend/src/main/java/org/dive4elements/river/importer/Importer.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/Importer.java Thu Sep 04 15:03:25 2014 +0200 @@ -30,7 +30,7 @@ import org.w3c.dom.Document; -import org.dive4elements.river.utils.StringUtil; +import org.dive4elements.river.backend.utils.StringUtil; /** Data Importer. Further processing happens per-river. */ public class Importer diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/ImporterSession.java --- a/backend/src/main/java/org/dive4elements/river/importer/ImporterSession.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/ImporterSession.java Thu Sep 04 15:03:25 2014 +0200 @@ -28,7 +28,7 @@ import org.dive4elements.river.model.DischargeTable; import org.dive4elements.river.model.Range; import org.dive4elements.river.model.River; -import org.dive4elements.river.utils.EpsilonComparator; +import org.dive4elements.river.backend.utils.EpsilonComparator; import org.dive4elements.artifacts.common.utils.LRUCache; public class ImporterSession diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/AbstractSedimentLoadParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/AbstractSedimentLoadParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/AbstractSedimentLoadParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -25,8 +25,8 @@ import org.dive4elements.river.model.GrainFraction; -import org.dive4elements.river.utils.DateUtil; -import org.dive4elements.river.utils.EpsilonComparator; +import org.dive4elements.river.backend.utils.DateUtil; +import org.dive4elements.river.backend.utils.EpsilonComparator; /** Parses sediment load files. */ public abstract class AbstractSedimentLoadParser extends LineParser { diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -40,8 +40,8 @@ import org.dive4elements.river.importer.ImportUnit; import org.dive4elements.river.model.BedHeightType; import org.dive4elements.river.importer.ImporterSession; -import org.dive4elements.river.utils.EpsilonComparator; -import org.dive4elements.river.utils.DateUtil; +import org.dive4elements.river.backend.utils.EpsilonComparator; +import org.dive4elements.river.backend.utils.DateUtil; public abstract class BedHeightParser { diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/DA50Parser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/DA50Parser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/DA50Parser.java Thu Sep 04 15:03:25 2014 +0200 @@ -22,11 +22,11 @@ import org.dive4elements.artifacts.common.utils.FileTools; -import org.dive4elements.river.utils.EpsilonComparator; +import org.dive4elements.river.backend.utils.EpsilonComparator; /** - * To create cross-sections, generate: Map> from files + * To create cross-sections, generate: Map[double,list[xy]] from files * in da50 format. */ public class DA50Parser extends LineParser implements CrossSectionParser diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/DA66Parser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/DA66Parser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/DA66Parser.java Thu Sep 04 15:03:25 2014 +0200 @@ -12,7 +12,7 @@ import org.dive4elements.river.importer.XY; -import org.dive4elements.river.utils.EpsilonComparator; +import org.dive4elements.river.backend.utils.EpsilonComparator; import java.io.File; import java.io.IOException; diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/FlowVelocityModelParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/FlowVelocityModelParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/FlowVelocityModelParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -25,7 +25,7 @@ import org.dive4elements.river.importer.ImportDischargeZone; import org.dive4elements.river.importer.ImportFlowVelocityModel; import org.dive4elements.river.importer.ImportFlowVelocityModelValue; -import org.dive4elements.river.utils.EpsilonComparator; +import org.dive4elements.river.backend.utils.EpsilonComparator; public class FlowVelocityModelParser extends LineParser { diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/NameAndTimeInterval.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/NameAndTimeInterval.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/NameAndTimeInterval.java Thu Sep 04 15:03:25 2014 +0200 @@ -14,7 +14,7 @@ import org.apache.log4j.Logger; import org.dive4elements.river.importer.ImportTimeInterval; -import org.dive4elements.river.utils.DateGuesser; +import org.dive4elements.river.backend.utils.DateGuesser; public class NameAndTimeInterval { diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/PorosityParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/PorosityParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/PorosityParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -12,7 +12,7 @@ import org.dive4elements.river.importer.ImportPorosity; import org.dive4elements.river.importer.ImportPorosityValue; import org.dive4elements.river.importer.ImportTimeInterval; -import org.dive4elements.river.utils.DateUtil; +import org.dive4elements.river.backend.utils.DateUtil; import java.io.File; import java.io.IOException; diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/SQRelationParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/SQRelationParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/SQRelationParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -22,7 +22,7 @@ import org.dive4elements.river.importer.ImportSQRelation; import org.dive4elements.river.importer.ImportSQRelationValue; import org.dive4elements.river.importer.ImportTimeInterval; -import org.dive4elements.river.utils.DateUtil; +import org.dive4elements.river.backend.utils.DateUtil; public class SQRelationParser extends LineParser { diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/W80CSVParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/W80CSVParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/W80CSVParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -14,8 +14,8 @@ import org.dive4elements.river.importer.parsers.tim.Coordinate; -import org.dive4elements.river.utils.DateGuesser; -import org.dive4elements.river.utils.EpsilonComparator; +import org.dive4elements.river.backend.utils.DateGuesser; +import org.dive4elements.river.backend.utils.EpsilonComparator; import java.io.File; import java.io.IOException; diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/W80Parser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/W80Parser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/W80Parser.java Thu Sep 04 15:03:25 2014 +0200 @@ -14,8 +14,8 @@ import org.dive4elements.river.importer.parsers.tim.Coordinate; -import org.dive4elements.river.utils.DateGuesser; -import org.dive4elements.river.utils.EpsilonComparator; +import org.dive4elements.river.backend.utils.DateGuesser; +import org.dive4elements.river.backend.utils.EpsilonComparator; import java.io.File; import java.io.IOException; diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelDifferencesParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelDifferencesParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelDifferencesParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -27,7 +27,7 @@ import org.dive4elements.river.importer.ImportWstQRange; import org.dive4elements.river.importer.ImportWstColumn; import org.dive4elements.river.importer.ImportWstColumnValue; -import org.dive4elements.river.utils.DateUtil; +import org.dive4elements.river.backend.utils.DateUtil; /** diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/WaterlevelParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -28,7 +28,7 @@ import org.dive4elements.river.importer.ImportWstColumn; import org.dive4elements.river.importer.ImportWstColumnValue; import org.dive4elements.river.importer.ImportWstQRange; -import org.dive4elements.river.utils.DateUtil; +import org.dive4elements.river.backend.utils.DateUtil; /** diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/WstParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -22,8 +22,8 @@ import org.apache.log4j.Logger; -import org.dive4elements.river.utils.StringUtil; -import org.dive4elements.river.utils.DateGuesser; +import org.dive4elements.river.backend.utils.StringUtil; +import org.dive4elements.river.backend.utils.DateGuesser; import java.util.regex.Pattern; import java.util.regex.Matcher; diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/importer/parsers/tim/TIMParser.java --- a/backend/src/main/java/org/dive4elements/river/importer/parsers/tim/TIMParser.java Thu Sep 04 13:00:55 2014 +0200 +++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/tim/TIMParser.java Thu Sep 04 15:03:25 2014 +0200 @@ -21,7 +21,7 @@ import org.apache.log4j.Logger; -import org.dive4elements.river.utils.EpsilonComparator; +import org.dive4elements.river.backend.utils.EpsilonComparator; /** Parser for single .tim files. */ public class TIMParser diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/utils/DBCPConnectionProvider.java --- a/backend/src/main/java/org/dive4elements/river/utils/DBCPConnectionProvider.java Thu Sep 04 13:00:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,261 +0,0 @@ -/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde - * Software engineering by Intevation GmbH - * - * This file is Free Software under the GNU AGPL (>=v3) - * and comes with ABSOLUTELY NO WARRANTY! Check out the - * documentation coming with Dive4Elements River for details. - */ - -/* - * Copyright 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.dive4elements.river.utils; - -import java.sql.Connection; -import java.sql.SQLException; - -import java.util.Iterator; -import java.util.Properties; -import java.util.Map; -import java.util.Collections; -import java.util.StringTokenizer; - -import org.apache.commons.dbcp.BasicDataSource; -import org.apache.commons.dbcp.BasicDataSourceFactory; - -import org.apache.log4j.Logger; - -import org.hibernate.HibernateException; - -import org.hibernate.connection.ConnectionProviderFactory; -import org.hibernate.connection.ConnectionProvider; - -import org.hibernate.cfg.Environment; - -/** - *

A connection provider that uses an Apache commons DBCP connection pool.

- * - *

To use this connection provider set:
- * hibernate.connection.provider_class org.hibernate.connection.DBCPConnectionProvider

- * - *
Supported Hibernate properties:
- *   hibernate.connection.driver_class
- *   hibernate.connection.url
- *   hibernate.connection.username
- *   hibernate.connection.password
- *   hibernate.connection.isolation
- *   hibernate.connection.autocommit
- *   hibernate.connection.pool_size
- *   hibernate.connection (JDBC driver properties)
- *
- * All DBCP properties are also supported by using the hibernate.dbcp prefix. - * A complete list can be found on the DBCP configuration page: - * http://jakarta.apache.org/commons/dbcp/configuration.html. - *
- *
Example:
- *   hibernate.connection.provider_class org.hibernate.connection.DBCPConnectionProvider
- *   hibernate.connection.driver_class org.hsqldb.jdbcDriver
- *   hibernate.connection.username sa
- *   hibernate.connection.password
- *   hibernate.connection.url jdbc:hsqldb:test
- *   hibernate.connection.pool_size 20
- *   hibernate.dbcp.initialSize 10
- *   hibernate.dbcp.maxWait 3000
- *   hibernate.dbcp.validationQuery select 1 from dual
- * - *

More information about configuring/using DBCP can be found on the - * DBCP website. - * There you will also find the DBCP wiki, mailing lists, issue tracking - * and other support facilities

- * - * @see org.hibernate.connection.ConnectionProvider - * @author Dirk Verbeeck - */ -public class DBCPConnectionProvider -implements ConnectionProvider -{ - private static Logger log = Logger.getLogger(DBCPConnectionProvider.class); - - private static final String PREFIX = "hibernate.dbcp."; - - private BasicDataSource ds; - - // Old Environment property for backward-compatibility - // (property removed in Hibernate3) - private static final String DBCP_PS_MAXACTIVE = - "hibernate.dbcp.ps.maxActive"; - - // Property doesn't exists in Hibernate2 - private static final String AUTOCOMMIT = - "hibernate.connection.autocommit"; - - public void configure(Properties props) throws HibernateException { - try { - log.debug("Configure DBCPConnectionProvider"); - - // DBCP properties used to create the BasicDataSource - Properties dbcpProperties = new Properties(); - - // DriverClass & url - String jdbcDriverClass = props.getProperty(Environment.DRIVER); - String jdbcUrl = props.getProperty(Environment.URL); - dbcpProperties.put("driverClassName", jdbcDriverClass); - dbcpProperties.put("url", jdbcUrl); - - // Username / password - String username = props.getProperty(Environment.USER); - String password = props.getProperty(Environment.PASS); - dbcpProperties.put("username", username); - dbcpProperties.put("password", password); - - // Isolation level - String isolationLevel = props.getProperty(Environment.ISOLATION); - if (isolationLevel != null - && (isolationLevel = isolationLevel.trim()).length() > 0) { - dbcpProperties.put("defaultTransactionIsolation", isolationLevel); - } - - // Turn off autocommit (unless autocommit property is set) - String autocommit = props.getProperty(AUTOCOMMIT); - if (autocommit != null - && (autocommit = autocommit.trim()).length() > 0) { - dbcpProperties.put("defaultAutoCommit", autocommit); - } else { - dbcpProperties.put("defaultAutoCommit", String.valueOf(Boolean.FALSE)); - } - - // Pool size - String poolSize = props.getProperty(Environment.POOL_SIZE); - if (poolSize != null - && (poolSize = poolSize.trim()).length() > 0 - && Integer.parseInt(poolSize) > 0) { - dbcpProperties.put("maxActive", poolSize); - } - - // Copy all "driver" properties into "connectionProperties" - Properties driverProps = - ConnectionProviderFactory.getConnectionProperties(props); - - if (driverProps.size() > 0) { - StringBuilder connectionProperties = new StringBuilder(); - for (Iterator iter = driverProps.entrySet().iterator(); - iter.hasNext(); - ) { - Map.Entry entry = (Map.Entry)iter.next(); - String key = (String)entry.getKey(); - String value = (String)entry.getValue(); - connectionProperties - .append(key) - .append('=') - .append(value); - if (iter.hasNext()) { - connectionProperties.append(';'); - } - } - dbcpProperties.put( - "connectionProperties", connectionProperties.toString()); - } - - // Copy all DBCP properties removing the prefix - for (Iterator iter = props.entrySet().iterator() ; iter.hasNext() ;) { - Map.Entry entry = (Map.Entry)iter.next(); - String key = (String)entry.getKey(); - if (key.startsWith(PREFIX)) { - String property = key.substring(PREFIX.length()); - String value = (String)entry.getValue(); - dbcpProperties.put(property, value); - } - } - - // Backward-compatibility - if (props.getProperty(DBCP_PS_MAXACTIVE) != null) { - dbcpProperties.put( - "poolPreparedStatements", - String.valueOf(Boolean.TRUE)); - dbcpProperties.put( - "maxOpenPreparedStatements", - props.getProperty(DBCP_PS_MAXACTIVE)); - } - - // Some debug info - /* // commented out, because it leaks the password - if (log.isDebugEnabled()) { - log.debug("Creating a DBCP BasicDataSource" + - " with the following DBCP factory properties:"); - StringWriter sw = new StringWriter(); - dbcpProperties.list(new PrintWriter(sw, true)); - log.debug(sw.toString()); - } - */ - - // Let the factory create the pool - ds = (BasicDataSource)BasicDataSourceFactory - .createDataSource(dbcpProperties); - - // This needs to be done manually as it is somehow ignored - // by the BasicDataSourceFactory if you set it as a dbcpProperty - String connectionInitSqls = props.getProperty("connectionInitSqls"); - if (connectionInitSqls != null) { - StringTokenizer tokenizer = new StringTokenizer(connectionInitSqls, ";"); - ds.setConnectionInitSqls(Collections.list(tokenizer)); - } - // The BasicDataSource has lazy initialization - // borrowing a connection will start the DataSource - // and make sure it is configured correctly. - - // Connection conn = ds.getConnection(); - // conn.close(); - } - catch (Exception e) { - String message = "Could not create a DBCP pool"; - log.fatal(message, e); - if (ds != null) { - BasicDataSource x = ds; ds = null; - try { - x.close(); - } - catch (SQLException sqle) { - } - } - throw new HibernateException(message, e); - } - log.debug("Configure DBCPConnectionProvider complete"); - } - - public Connection getConnection() throws SQLException { - return ds.getConnection(); - } - - public void closeConnection(Connection conn) throws SQLException { - conn.close(); - } - - public void close() throws HibernateException { - try { - if (ds != null) { - BasicDataSource x = ds; ds = null; - x.close(); - } - } - catch (SQLException sqle) { - throw new HibernateException("Could not close DBCP pool", sqle); - } - } - - public boolean supportsAggressiveRelease() { - return false; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/utils/DateGuesser.java --- a/backend/src/main/java/org/dive4elements/river/utils/DateGuesser.java Thu Sep 04 13:00:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,266 +0,0 @@ -/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde - * Software engineering by Intevation GmbH - * - * This file is Free Software under the GNU AGPL (>=v3) - * and comes with ABSOLUTELY NO WARRANTY! Check out the - * documentation coming with Dive4Elements River for details. - */ - -package org.dive4elements.river.utils; - -import java.util.Date; -import java.util.Calendar; - -import java.util.regex.Pattern; -import java.util.regex.Matcher; - -public final class DateGuesser { - public static final String [] MONTH = { - "jan", "feb", "mrz", "apr", "mai", "jun", - "jul", "aug", "sep", "okt", "nov", "dez" - }; - - public static final int guessMonth(String s) { - s = s.toLowerCase(); - for (int i = 0; i < MONTH.length; ++i) - if (MONTH[i].equals(s)) { - return i; - } - return -1; - } - - public static final Pattern YYYY_MM_DD = - Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})$"); - - public static final Pattern DD_MM_YYYY = - Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})$"); - - public static final Pattern MMM_YYYY = - Pattern.compile("^(\\d{0,2})\\.?(\\w{3})\\.?(\\d{2,4})$"); - - public static final Pattern GARBAGE_YYYY = - Pattern.compile("^\\D*(\\d{2,4})$"); - - public static final Pattern YYYY_MM_DDThh_mm = - Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2})$"); - - public static final Pattern YYYY_MM_DDThh_mm_ss = - Pattern.compile("^(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})$"); - - public static final Pattern DD_MM_YYYYThh_mm = - Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})T(\\d{1,2}):(\\d{2})$"); - - public static final Pattern DD_MM_YYYYThh_mm_ss = - Pattern.compile("^(\\d{1,2})\\.(\\d{1,2})\\.(\\d{2,4})T(\\d{1,2}):(\\d{2}):(\\d{2})$"); - - public static final Pattern DDMMYY = - Pattern.compile("^(\\d{2})(\\d{2})(\\d{2})$"); - - private DateGuesser() { - } - - public static final int calendarMonth(String month) { - return calendarMonth(Integer.parseInt(month)); - } - - public static final int calendarMonth(int month) { - return Math.max(Math.min(month-1, 11), 0); - } - - /** - * Guess date by trying all different patterns. - * Throws IllegalArgumentException if not able to guess. - * @param s The date to be guessed (e.g. 11.02.2001). - * @return the parsed Date. - */ - public static Date guessDate(String s) { - if (s == null || (s = s.trim()).length() == 0) { - throw new IllegalArgumentException(); - } - - Matcher m; - - m = YYYY_MM_DD.matcher(s); - - if (m.matches()) { - Calendar cal = Calendar.getInstance(); - String year = m.group(1); - String month = m.group(2); - String day = m.group(3); - cal.clear(); - cal.set( - Integer.parseInt(year), - calendarMonth(month), - Integer.parseInt(day), - 12, 0, 0); - return cal.getTime(); - } - - m = DD_MM_YYYY.matcher(s); - - if (m.matches()) { - Calendar cal = Calendar.getInstance(); - String year = m.group(3); - String month = m.group(2); - String day = m.group(1); - cal.clear(); - cal.set( - Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), - calendarMonth(month), - Integer.parseInt(day), - 12, 0, 0); - return cal.getTime(); - } - - m = MMM_YYYY.matcher(s); - - if (m.matches()) { - int month = guessMonth(m.group(2)); - if (month >= 0) { - Calendar cal = Calendar.getInstance(); - String year = m.group(3); - String day = m.group(1); - cal.clear(); - cal.set( - Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), - month, - day.length() == 0 ? 15 : Integer.parseInt(day), - 12, 0, 0); - return cal.getTime(); - } - } - - m = YYYY_MM_DDThh_mm.matcher(s); - - if (m.matches()) { - Calendar cal = Calendar.getInstance(); - String year = m.group(1); - String month = m.group(2); - String day = m.group(3); - String hour = m.group(4); - String minute = m.group(5); - cal.clear(); - cal.set( - Integer.parseInt(year), - calendarMonth(month), - Integer.parseInt(day), - Integer.parseInt(hour), - Integer.parseInt(minute), - 0 - ); - return cal.getTime(); - } - - m = YYYY_MM_DDThh_mm_ss.matcher(s); - - if (m.matches()) { - Calendar cal = Calendar.getInstance(); - String year = m.group(1); - String month = m.group(2); - String day = m.group(3); - String hour = m.group(4); - String minute = m.group(5); - String second = m.group(6); - cal.clear(); - cal.set( - Integer.parseInt(year), - calendarMonth(month), - Integer.parseInt(day), - Integer.parseInt(hour), - Integer.parseInt(minute), - Integer.parseInt(second) - ); - return cal.getTime(); - } - - m = DD_MM_YYYYThh_mm.matcher(s); - - if (m.matches()) { - Calendar cal = Calendar.getInstance(); - String year = m.group(3); - String month = m.group(2); - String day = m.group(1); - String hour = m.group(4); - String minute = m.group(5); - cal.clear(); - cal.set( - Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), - calendarMonth(month), - Integer.parseInt(day), - Integer.parseInt(hour), - Integer.parseInt(minute), - 0 - ); - return cal.getTime(); - } - - m = DD_MM_YYYYThh_mm_ss.matcher(s); - - if (m.matches()) { - Calendar cal = Calendar.getInstance(); - String year = m.group(3); - String month = m.group(2); - String day = m.group(1); - String hour = m.group(4); - String minute = m.group(5); - String second = m.group(6); - cal.clear(); - cal.set( - Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), - calendarMonth(month), - Integer.parseInt(day), - Integer.parseInt(hour), - Integer.parseInt(minute), - Integer.parseInt(second) - ); - return cal.getTime(); - } - - m = DDMMYY.matcher(s); - - if (m.matches()) { - Calendar cal = Calendar.getInstance(); - String day = m.group(1); - String month = m.group(2); - String yearS = m.group(3); - int year = Integer.parseInt(yearS); - - if (year <= cal.get(Calendar.YEAR) % 100) { - year += 2000; - } - else { - year += 1900; - } - cal.clear(); - cal.set( - year, - Integer.parseInt(month), // month - Integer.parseInt(day), // day - 12, 0, 0); - return cal.getTime(); - } - - m = GARBAGE_YYYY.matcher(s); - - if (m.matches()) { - Calendar cal = Calendar.getInstance(); - String year = m.group(1); - cal.clear(); - cal.set( - Integer.parseInt(year) + (year.length() == 2 ? 1900 : 0), - 5, // month - 15, // day - 12, 0, 0); - return cal.getTime(); - } - - throw new IllegalArgumentException(); - } - - public static void main(String [] args) { - for (int i = 0; i < args.length; ++i) { - System.out.println(args[i] + ": " + guessDate(args[i])); - } - } -} -// end of file diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/utils/DateUtil.java --- a/backend/src/main/java/org/dive4elements/river/utils/DateUtil.java Thu Sep 04 13:00:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* Copyright (C) 2014 by Bundesanstalt für Gewässerkunde - * Software engineering by Intevation GmbH - * - * This file is Free Software under the GNU AGPL (>=v3) - * and comes with ABSOLUTELY NO WARRANTY! Check out the - * documentation coming with Dive4Elements River for details. - */ - -package org.dive4elements.river.utils; - -import java.util.Date; -import java.util.Calendar; - -public final class DateUtil { - - private DateUtil() { - } - - /** Create Date on first moment (1st jan) of given year. */ - public static Date getStartDateFromYear(int year) { - Calendar cal = Calendar.getInstance(); - cal.clear(); - cal.set(year, 0, 1, 0, 0, 0); - - return cal.getTime(); - } - - - /** Create Date on last moment (31st dec) of given year. */ - public static Date getEndDateFromYear(int year) { - Calendar cal = Calendar.getInstance(); - cal.clear(); - cal.set(year, 11, 31, 23, 59, 59); - - return cal.getTime(); - } -} diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/utils/DouglasPeuker.java --- a/backend/src/main/java/org/dive4elements/river/utils/DouglasPeuker.java Thu Sep 04 13:00:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -package org.dive4elements.river.utils; - -import org.dive4elements.river.importer.XY; // TODO: Move to a more common package. - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public final class DouglasPeuker -{ - public static final double EPSILON = 1e-4; - - private DouglasPeuker() { - } - - public static List simplify(List input) { - return simplify(input, EPSILON); - } - - public static List simplify(List input, double epsilon) { - - int N = input.size(); - - if (N < 3) { - return new ArrayList(input); - } - - List simplified = recursiveSimplify(input, 0, N-1, epsilon); - - List output = new ArrayList(simplified.size()+2); - output.add(input.get(0)); - output.addAll(simplified); - output.add(input.get(N-1)); - - return output; - } - - private static List recursiveSimplify( - List input, - int start, - int end, - double epsilon - ) { - XY a = input.get(start); - XY b = input.get(end); - - // Normal of hesse normal form. - XY n = new XY(b).sub(a).ortho().normalize(); - - // distance offset of the hesse normal form. - double d = n.lineOffset(a); - - double maxDist = -Double.MAX_VALUE; - int maxIdx = -1; - - for (int i = start+1; i < end; ++i) { - double dist = Math.abs(n.dot(input.get(i)) + d); - if (dist > maxDist) { - maxDist = dist; - maxIdx = i; - } - } - - if (maxDist < epsilon) { - // All points between a and b can be ignored. - return Collections.emptyList(); - } - - // Split by input[maxIdx]. - List before = recursiveSimplify(input, start, maxIdx, epsilon); - List after = recursiveSimplify(input, maxIdx, end, epsilon); - - List output = new ArrayList(before.size()+1+after.size()); - output.addAll(before); - output.add(input.get(maxIdx)); - output.addAll(after); - - return output; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/utils/EpsilonComparator.java --- a/backend/src/main/java/org/dive4elements/river/utils/EpsilonComparator.java Thu Sep 04 13:00:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde - * Software engineering by Intevation GmbH - * - * This file is Free Software under the GNU AGPL (>=v3) - * and comes with ABSOLUTELY NO WARRANTY! Check out the - * documentation coming with Dive4Elements River for details. - */ - -package org.dive4elements.river.utils; - -import java.util.Comparator; -import java.io.Serializable; - -/** Comparator with some tolerance (epsilon). */ -public class EpsilonComparator implements Comparator, Serializable -{ - public static final double EPSILON = 1e-4; - - /** Ready-made comparator with 1e-4 tolerance. */ - public static final EpsilonComparator CMP = new EpsilonComparator(EPSILON); - - private double epsilon; - - public EpsilonComparator(double epsilon) { - this.epsilon = epsilon; - } - - @Override - public int compare(Double a, Double b) { - double diff = a - b; - if (diff < -epsilon) return -1; - if (diff > epsilon) return +1; - return 0; - } -} -// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 : diff -r a1ceacf15d3a -r 3bb1c62ad732 backend/src/main/java/org/dive4elements/river/utils/StringUtil.java --- a/backend/src/main/java/org/dive4elements/river/utils/StringUtil.java Thu Sep 04 13:00:55 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,828 +0,0 @@ -/* Copyright (C) 2011, 2012, 2013 by Bundesanstalt für Gewässerkunde - * Software engineering by Intevation GmbH - * - * This file is Free Software under the GNU AGPL (>=v3) - * and comes with ABSOLUTELY NO WARRANTY! Check out the - * documentation coming with Dive4Elements River for details. - */ - -package org.dive4elements.river.utils; - -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Locale; - -import java.net.URLEncoder; -import java.net.URLDecoder; - -import java.io.UnsupportedEncodingException; -import java.io.IOException; -import java.io.BufferedReader; -import java.io.StringReader; -import java.io.StringWriter; -import java.io.PrintWriter; - - -public final class StringUtil { - final static String NUMBER_SEPERATOR = ";"; - final static String LINE_SEPERATOR = ":"; - - private StringUtil() { - } - - public static final String double2DArrayToString(double[][] values) { - - if (values == null) { - throw new IllegalArgumentException("keine double[][]-Werte"); - } - - StringBuilder strbuf = new StringBuilder(); - - for (int i=0; i < values.length; i++) { - if (i>0) { - strbuf.append(LINE_SEPERATOR); - } - for (int j=0; j < values[i].length; j++) { - if (j > 0) { - strbuf.append(NUMBER_SEPERATOR); - } - strbuf.append(values[i][j]); - } - } - - return strbuf.toString(); - } - - public static final double[][] stringToDouble2DArray(String str) { - if (str == null || str.length() == 0) { - return null; - } - - String[] lineSplit = str.split(LINE_SEPERATOR); - double[][] array2D = new double[lineSplit.length][]; - for (int i=0; i < lineSplit.length; i++) { - String[] numberSplit = lineSplit[i].split(NUMBER_SEPERATOR); - - double[] numbers = new double[numberSplit.length]; - for (int j=0; j < numberSplit.length; j++) { - numbers[j] = Double.valueOf(numberSplit[j]).doubleValue(); - } - - array2D[i] = numbers; - } - - return array2D; - } - - /** - * Remove first occurrence of "[" and "]" (if both do occur). - * @param value String to be stripped of [] (might be null). - * @return input string but with [ and ] removed, or input string if no - * brackets were found. - */ - public static final String unbracket(String value) { - // null- guard - if (value == null) return value; - - int start = value.indexOf("["); - int end = value.indexOf("]"); - - if (start < 0 || end < 0) { - return value; - } - - value = value.substring(start + 1, end); - - return value; - } - - - /** - * From "Q=1" make "W(Q=1)". - * @return original string wraped in "W()" if it contains a "Q", original - * string otherwise. - */ - public static String wWrap(String wOrQ) { - return (wOrQ != null && wOrQ.indexOf("Q") >=0) - ? "W(" + wOrQ + ")" - : wOrQ; - } - - - public static final String [] splitLines(String s) { - if (s == null) { - return null; - } - ArrayList list = new ArrayList(); - - BufferedReader in = null; - - try { - in = - new BufferedReader( - new StringReader(s)); - - String line; - - while ((line = in.readLine()) != null) { - list.add(line); - } - } - catch (IOException ioe) { - return null; - } - finally { - if (in != null) - try { - in.close(); - } - catch (IOException ioe) {} - } - - return list.toArray(new String[list.size()]); - } - - public static final String concat(String [] s) { - return concat(s, null); - } - - public static final String concat(String [] s, String glue) { - if (s == null) { - return null; - } - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < s.length; ++i) { - if (i > 0 && glue != null) { - sb.append(glue); - } - sb.append(s[i]); - } - return sb.toString(); - } - - public static final String [] splitAfter(String [] src, int N) { - if (src == null) { - return null; - } - - ArrayList list = new ArrayList(src.length); - for (int i = 0; i < src.length; ++i) { - String s = src[i]; - int R; - if (s == null || (R = s.length()) == 0) { - list.add(s); - } - else { - while (R > N) { - list.add(s.substring(0, N)); - s = s.substring(N); - R = s.length(); - } - list.add(s); - } - } - return list.toArray(new String[list.size()]); - } - - public static final String [] splitQuoted(String s) { - return splitQuoted(s, '"'); - } - - public static final String[] fitArray(String [] src, String [] dst) { - if (src == null) { - return dst; - } - if (dst == null) { - return src; - } - - if (src.length == dst.length) { - return src; - } - - System.arraycopy(src, 0, dst, 0, Math.min(dst.length, src.length)); - - return dst; - } - - public static final String [] splitQuoted(String s, char quoteChar) { - if (s == null) { - return null; - } - ArrayList l = new ArrayList(); - int mode = 0, last_mode = 0; - StringBuilder sb = new StringBuilder(); - for (int N = s.length(), i = 0; i < N; ++i) { - char c = s.charAt(i); - switch (mode) { - case 0: // unquoted mode - if (c == quoteChar) { - mode = 1; // to quoted mode - if (sb.length() > 0) { - l.add(sb.toString()); - sb.setLength(0); - } - } - else if (c == '\\') { - last_mode = 0; - mode = 2; // escape mode - } - else if (!Character.isWhitespace(c)) { - sb.append(c); - } - else if (sb.length() > 0) { - l.add(sb.toString()); - sb.setLength(0); - } - break; - case 1: // quote mode - if (c == '\\') { - last_mode = 1; - mode = 2; // escape mode - } - else if (c == quoteChar) { // leave quote mode - l.add(sb.toString()); - sb.setLength(0); - mode = 0; // to unquoted mode - } - else { - sb.append(c); - } - break; - case 2: // escape mode - sb.append(c); - mode = last_mode; - break; - } - } - if (sb.length() > 0) { - l.add(sb.toString()); - } - return l.toArray(new String[l.size()]); - } - - public static final String [] splitUnique(String s) { - return splitUnique(s, "[\\s,]+"); - } - - public static final String [] splitUnique(String s, String sep) { - return s != null ? unique(s.split(sep)) : null; - } - - public static final String [] unique(String [] str) { - if (str == null || str.length == 1) { - return str; - } - - Arrays.sort(str); - - for (int i = 1; i < str.length; ++i) - if (str[i].equals(str[i-1])) { - ArrayList list = new ArrayList(str.length); - - for (int j = 0; j < i; ++j) { - list.add(str[j]); - } - - String last = str[i]; - - for (++i; i < str.length; ++i) - if (!last.equals(str[i])) { - list.add(last = str[i]); - } - - return list.toArray(new String[list.size()]); - } - - return str; - } - - public static final String [] ensureEmptyExistence(String [] str) { - if (str == null) { - return null; - } - - for (int i = 0; i < str.length; ++i) - if (str[i].length() == 0) { - if (i != 0) { // copy to front - String t = str[0]; - str[0] = str[i]; - str[i] = t; - } - return str; - } - - String [] n = new String[str.length+1]; - n[0] = ""; - System.arraycopy(str, 0, n, 1, str.length); - return n; - } - - public static final String ensureWidthPadLeft(String s, int width, char pad) { - int N = s.length(); - if (N >= width) { - return s; - } - StringBuilder sb = new StringBuilder(width); - for (; N < width; ++N) { - sb.append(pad); - } - sb.append(s); - return sb.toString(); - } - - public static final String [] splitWhiteSpaceWithNAsPad( - String s, - int N, - String pad - ) { - if (s == null) { - return null; - } - - boolean copyChars = true; - int count = 0; // number of WS - - int S = s.length(); - - ArrayList parts = new ArrayList(); - - StringBuilder part = new StringBuilder(S); - - for (int i = 0; i < S; ++i) { - char c = s.charAt(i); - if (copyChars) { // char mode - if (Character.isWhitespace(c)) { - if (part.length() > 0) { - parts.add(part.toString()); - part.setLength(0); - } - count = 1; - copyChars = false; // to WS mode - } - else { - part.append(c); - } - } - else { // counting WS - if (Character.isWhitespace(c)) { - ++count; - } - else { - while (count >= N) {// enough to insert pad? - parts.add(pad); - count -= N; - } - part.append(c); - count = 0; - copyChars = true; // back to char mode - } - } - } // for all chars - - if (copyChars) { - if (part.length() > 0) { - parts.add(part.toString()); - } - } - else { - while (count >= N) { // enough to insert pad? - parts.add(pad); - count -= N; - } - } - - return parts.toArray(new String[parts.size()]); - } - - public static final String encodeURL(String url) { - try { - return url != null - ? URLEncoder.encode(url, "UTF-8") - : ""; - } - catch (UnsupportedEncodingException usee) { - throw new RuntimeException(usee.getLocalizedMessage()); - } - } - - public static final String decodeURL(String url) { - try { - return url != null - ? URLDecoder.decode(url, "UTF-8") - : ""; - } - catch (UnsupportedEncodingException usee) { - throw new RuntimeException(usee.getLocalizedMessage()); - } - } - - public static final boolean isEmpty(String s) { - return s == null || s.length() == 0; - } - - public static final String empty(String s) { - return s == null ? "" : s; - } - - - public static final String trim(String s) { - return s != null ? s.trim() : null; - } - - public static final String uniqueWhitespaces(String s) { - if (s == null) { - return null; - } - - boolean wasWS = false; - StringBuilder sb = new StringBuilder(); - - for (int N = s.length(), i = 0; i < N; ++i) { - char c = s.charAt(i); - if (Character.isWhitespace(c)) { - if (!wasWS) { - sb.append(c); - wasWS = true; - } - } - else { - sb.append(c); - wasWS = false; - } - } - - return sb.toString(); - } - - public static final String replaceNewlines(String s) { - return s == null - ? null - : s.replace('\r', ' ').replace('\n', ' '); - } - - /* - public static final String quoteReplacement(String s) { - - if (s == null || (s.indexOf('\\') == -1 && s.indexOf('$') == -1)) - return s; - - StringBuilder sb = new StringBuilder(); - - for (int N = s.length(), i = 0; i < N; ++i) { - char c = s.charAt(i); - if (c == '\\' || c == '$') sb.append('\\'); - sb.append(c); - } - - return sb.toString(); - } - */ - - public static final String quoteReplacement(String s) { - - if (s == null) { - return null; - } - - for (int N = s.length(), i = 0; i < N; ++i) { // plain check loop - char c = s.charAt(i); - if (c == '$' || c == '\\') { // first special -> StringBuilder - StringBuilder sb = new StringBuilder(s.substring(0, i)) - .append('\\') - .append(c); - for (++i; i < N; ++i) { // build StringBuilder with rest - if ((c = s.charAt(i)) == '$' || c == '\\') { - sb.append('\\'); - } - sb.append(c); - } - return sb.toString(); - } - } - - return s; - } - - public static final String repeat(String what, int times) { - return repeat(what, times, new StringBuilder()).toString(); - } - - public static final StringBuilder repeat(String what, int times, StringBuilder sb) { - while (times-- > 0) { - sb.append(what); - } - return sb; - } - - /** - * Returns the file name without extension. - */ - public static final String cutExtension(String s) { - if (s == null) { - return null; - } - int dot = s.lastIndexOf('.'); - return dot >= 0 - ? s.substring(0, dot) - : s; - } - - public static final String extension(String s) { - if (s == null) { - return null; - } - int dot = s.lastIndexOf('.'); - return dot >= 0 - ? s.substring(dot+1) - : s; - } - - public static final String [] splitExtension(String x) { - if (x == null) { - return null; - } - int i = x.lastIndexOf('.'); - return i < 0 - ? new String[] { x, null } - : new String[] { x.substring(0, Math.max(0, i)), x.substring(i+1).toLowerCase() }; - } - - public static String entityEncode(String s) { - if (s == null || s.length() == 0) { - return s; - } - - StringBuilder sb = new StringBuilder(); - for (int i=0, N =s.length(); i < N; i++) { - char c = s.charAt(i); - switch (c) { - case '<': - sb.append("<"); - break; - case '>': - sb.append(">"); - break; - case '&': - sb.append("&"); - break; - default: - sb.append(c); - } - } - return sb.toString(); - } - - public static String entityDecode(String s) { - if (s == null || s.length() == 0) { - return s; - } - - boolean amp = false; - StringBuilder sb = new StringBuilder(); - StringBuilder ampbuf = new StringBuilder(); - for (int i=0, N =s.length(); i < N; i++) { - char c = s.charAt(i); - if (amp) { - if (c == ';') { - amp = false; - String str = ampbuf.toString(); - ampbuf.setLength(0); - if (str.equals("lt")) { - sb.append('<'); - } - else if (str.equals("gt")) { - sb.append('>'); - } - else if (str.equals("amp")) { - sb.append('&'); - } - else { - sb.append('&').append(str).append(';'); - } - } - else { - ampbuf.append(c); - } - } - else if (c=='&') { - amp = true; - } - else { - sb.append(c); - } - - } - return sb.toString(); - } - - public static final String quote(String s) { - return quote(s, '"'); - } - - public static final String quote(String s, char quoteChar) { - if (s == null) { - return null; - } - - int N = s.length(); - - if (N == 0) - return new StringBuilder(2) - .append(quoteChar) - .append(quoteChar) - .toString(); - - StringBuilder sb = null; - - int i = 0; - - for (; i < N; ++i) { - char c = s.charAt(i); - - if (Character.isWhitespace(c)) { - sb = new StringBuilder() - .append(quoteChar) - .append(s.substring(0, i+1)); - break; - } - else if (c == quoteChar) { - sb = new StringBuilder() - .append(quoteChar) - .append(s.substring(0, i)) - .append('\\') - .append(quoteChar); - break; - } - } - - if (sb == null) { - return s; - } - - for (++i; i < N; ++i) { - char c = s.charAt(i); - if (c == quoteChar || c == '\\') { - sb.append('\\'); - } - - sb.append(c); - } - - return sb.append(quoteChar).toString(); - } - - /* - public static String sprintf(String format, Object... args) { - return sprintf(null, format, args); - } - */ - - public static String sprintf(Locale locale, String format, Object ... args) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - pw.printf(locale, format, args); - pw.flush(); - return sw.toString(); - } - - - public static void testQuote() { - System.err.println("testing quote:"); - - String cases [] = { - "", "''", - "test", "test", - "test test", "'test test'", - " test", "' test'", - "test ", "'test '", - " test ", "' test '", - "'test", "'\\'test'", - "'", "'\\''", - " ' ' ", "' \\' \\' '", - "te'st", "'te\\'st'" - }; - - int failed = 0; - - for (int i = 0; i < cases.length; i += 2) { - String in = cases[i]; - String out = cases[i+1]; - - String res = quote(in, '\''); - if (!res.equals(out)) { - ++failed; - System.err.println( - "quote failed on: >" + in + - "< result: >" + res + - "< expected: >" + out + "<"); - } - } - - int T = cases.length/2; - - System.err.println("tests total: " + T); - System.err.println("tests failed: " + failed); - System.err.println("tests passed: " + (T - failed)); - } - - public static void testQuoteReplacement() { - System.err.println("testing quoteReplacement:"); - - String cases [] = { - "", "", - "test", "test", - "$", "\\$", - "\\", "\\\\", - "\\$", "\\\\\\$", - "test\\$", "test\\\\\\$", - "\\test", "\\\\test", - "test$", "test\\$", - "test$test", "test\\$test", - "$test$", "\\$test\\$" - }; - - int failed = 0; - - for (int i = 0; i < cases.length; i += 2) { - String in = cases[i]; - String out = cases[i+1]; - - String res = quoteReplacement(in); - if (!res.equals(out)) { - ++failed; - System.err.println( - "quoteReplacement failed on: '" + in + - "' result: '" + res + - "' expected: '" + out + "'"); - } - } - - int T = cases.length/2; - - System.err.println("tests total: " + T); - System.err.println("tests failed: " + failed); - System.err.println("tests passed: " + (T - failed)); - } - - public static void testStringArray2D() { - int total = 0; - int fail = 0; - int passed = 0; - - System.err.println("testing StringArray2D:"); - - double[][] testarray = {{1.0, 2.0, 3.0}, - {1.1, 2.1, 3.1}, - {100.2, 200.2} - }; - String str = double2DArrayToString(testarray); - - total += 1; - if (str.equals("1.0;2.0;3.0:1.1;2.1;3.1:100.2;200.2")) { - passed +=1; - } - else { - fail +=1; - System.err.println("Der Ergebnis-String ist nicht richtig:"); - System.err.println(str); - } - - - - double[][] testarray2 = stringToDouble2DArray(str); - boolean failed = false; - - total +=1; - for (int i=0; i < testarray.length; i++) - for (int j=0; j < testarray[i].length; j++) - if (testarray[i][j] != testarray2[i][j]) { - System.err.println("Test scheitert bei i=" +i +" j=" +j); - System.err.println("alter Wert=" + testarray[i][j] +" neuer Wert=" +testarray2[i][j]); - failed = true; - } - if (failed) { - fail +=1; - } - else { - passed +=1; - } - System.err.println("tests total: "+ total); - System.err.println("tests failed: "+ fail); - System.err.println("tests passed: "+ passed); - } - - public static void main(String [] args) { - - testQuoteReplacement(); - testQuote(); - testStringArray2D(); - } - - /** Check for occurence of needle in hay, converting both to lowercase - * to be ignorant of cases. */ - public static boolean containsIgnoreCase(String hay, String needle) { - return hay.toLowerCase().contains(needle.toLowerCase()); - } -} -// end of file