changeset 8975:a0a0a7f912ab

Added new columns bed_height.comment and sounding_width_info; extended the bed height parser for the new meta data and the min/max_height columns
author mschaefer
date Tue, 03 Apr 2018 10:40:57 +0200 (2018-04-03)
parents a275ddf7a3a1
children e541938dd3ab
files backend/src/main/java/org/dive4elements/river/importer/ImportBedHeight.java backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightValue.java backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java backend/src/main/java/org/dive4elements/river/model/BedHeight.java backend/src/main/java/org/dive4elements/river/model/BedHeightValue.java
diffstat 5 files changed, 415 insertions(+), 488 deletions(-) [+]
line wrap: on
line diff
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeight.java	Tue Apr 03 10:37:30 2018 +0200
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeight.java	Tue Apr 03 10:40:57 2018 +0200
@@ -12,15 +12,13 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
 import org.dive4elements.river.model.BedHeight;
 import org.dive4elements.river.model.BedHeightType;
 import org.dive4elements.river.model.ElevationModel;
 import org.dive4elements.river.model.Range;
 import org.dive4elements.river.model.River;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 public class ImportBedHeight
@@ -37,165 +35,155 @@
     protected ImportLocationSystem locationSystem;
     protected ImportElevationModel curElevationModel;
     protected ImportElevationModel oldElevationModel;
+    protected String sounding_width_info;
+    protected String comment;
 
     protected List<ImportBedHeightValue> values;
 
     protected BedHeight peer;
 
 
-    public ImportBedHeight(String description) {
+    public ImportBedHeight(final String description) {
         this.description = description;
-        this.values      = new ArrayList<ImportBedHeightValue>();
+        this.values      = new ArrayList<>();
     }
 
 
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
     public int getValueCount() {
-        return values.size();
+        return this.values.size();
     }
 
 
-    public void setYear(int year) {
+    public void setYear(final int year) {
         this.year = year;
     }
 
-    public void setTimeInterval(ImportTimeInterval timeInterval) {
+    public void setTimeInterval(final ImportTimeInterval timeInterval) {
         // do nothing
     }
 
-    public void setEvaluationBy(String evaluationBy) {
+    public void setEvaluationBy(final String evaluationBy) {
         this.evaluationBy = evaluationBy;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
-    public void setRange(ImportRange range) {
+    public void setRange(final ImportRange range) {
         this.range = range;
     }
 
-    public void setType(ImportBedHeightType type) {
+    public void setType(final ImportBedHeightType type) {
         this.type = type;
     }
 
-    public void setLocationSystem(ImportLocationSystem locationSystem) {
+    public void setLocationSystem(final ImportLocationSystem locationSystem) {
         this.locationSystem = locationSystem;
     }
 
-    public void setCurElevationModel(ImportElevationModel curElevationModel) {
+    public void setCurElevationModel(final ImportElevationModel curElevationModel) {
         this.curElevationModel = curElevationModel;
     }
 
-    public void setOldElevationModel(ImportElevationModel oldElevationModel) {
+    public void setOldElevationModel(final ImportElevationModel oldElevationModel) {
         this.oldElevationModel = oldElevationModel;
     }
 
-    public void addValue(ImportBedHeightValue value) {
-        values.add((ImportBedHeightValue) value);
+    public void setSoundingWidthInfo(final String sounding_width_info) {
+        this.sounding_width_info = sounding_width_info;
     }
 
-    public void storeDependencies(River river) {
+    public void setComment(final String comment) {
+        this.comment = comment;
+    }
+
+    public void addValue(final ImportBedHeightValue value) {
+        this.values.add(value);
+    }
+
+    public void storeDependencies(final River river) {
         log.info("Store dependencies for single: '" + getDescription() + "'");
 
-        if (type != null) {
-            type.storeDependencies();
+        if (this.type != null) {
+            this.type.storeDependencies();
         }
 
-        if (locationSystem != null) {
-            locationSystem.storeDependencies();
-        }
-
-        if (curElevationModel != null) {
-            curElevationModel.storeDependencies();
+        if (this.locationSystem != null) {
+            this.locationSystem.storeDependencies();
         }
 
-        if (oldElevationModel != null) {
-            oldElevationModel.storeDependencies();
+        if (this.curElevationModel != null) {
+            this.curElevationModel.storeDependencies();
         }
 
-        BedHeight peer = getPeer(river);
+        if (this.oldElevationModel != null) {
+            this.oldElevationModel.storeDependencies();
+        }
+
+        final BedHeight peer = getPeer(river);
 
         if (peer != null) {
-            for (ImportBedHeightValue value: values) {
+            for (final ImportBedHeightValue value: this.values) {
                 value.storeDependencies(peer);
             }
         }
 
-        Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
         session.flush();
     }
 
-    public BedHeight getPeer(River river) {
-        if (peer == null) {
-            BedHeightType  theType     = type != null ? type.getPeer() : null;
-            ElevationModel theCurModel = curElevationModel.getPeer();
-            Range          theRange    = range != null
-                ? range.getPeer(river)
-                : null;
-
-            if (theType == null) {
-                log.warn("BHS: No bed height type given. Skip file '" +
-                    description + "'");
-                return null;
-            }
-
-            if (theCurModel == null) {
-                log.warn("BHS: No elevation model given. Skip file '" +
-                    description + "'");
-                return null;
-            }
-
-            if (theRange == null) {
-                log.warn("BHS: No km-range given: '" +
-                    description + "'");
-            }
-
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
+    public BedHeight getPeer(final River river) {
+        if (this.peer != null)
+            return null;
 
-            Query query = session.createQuery(
-                "from BedHeight where " +
-                "river=:river and year=:year " +
-                "and type=:type and locationSystem=:locationSystem and " +
-                "curElevationModel=:curElevationModel and range=:range");
-
-            query.setParameter("river", river);
-            query.setParameter("year", year);
-            query.setParameter("type", theType);
-            query.setParameter("locationSystem", locationSystem.getPeer());
-            query.setParameter("curElevationModel", theCurModel);
-            query.setParameter("range", range.getPeer(river));
-
-            List<BedHeight> bedHeights = query.list();
-            if (bedHeights.isEmpty()) {
-                log.info("Create new BedHeight DB instance.");
+        final BedHeightType theType = this.type != null ? this.type.getPeer() : null;
+        final ElevationModel theCurModel = this.curElevationModel.getPeer();
+        final Range theRange = (this.range != null) ? this.range.getPeer(river) : null;
 
-                peer = new BedHeight(
-                    river,
-                    year,
-                    theType,
-                    locationSystem.getPeer(),
-                    theCurModel,
-                    oldElevationModel != null
-                        ? oldElevationModel.getPeer()
-                        : null,
-                    range.getPeer(river),
-                    evaluationBy,
-                    description
-                );
-
-                session.save(peer);
-            }
-            else {
-                peer = bedHeights.get(0);
-            }
+        if (theType == null) {
+            log.warn("BHS: No bed height type given. Skip file '" + this.description + "'");
+            return null;
         }
 
-        return peer;
+        if (theCurModel == null) {
+            log.warn("BHS: No elevation model given. Skip file '" + this.description + "'");
+            return null;
+        }
+
+        if (theRange == null) {
+            log.warn("BHS: No km-range given: '" + this.description + "'");
+        }
+
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+
+        final Query query = session.createQuery("FROM BedHeight WHERE (river=:river) AND (year=:year)"
+                + " AND (type=:type) AND (locationSystem=:locationSystem)"
+                + " AND (curElevationModel=:curElevationModel) AND (range=:range)");
+        query.setParameter("river", river);
+        query.setParameter("year", this.year);
+        query.setParameter("type", theType);
+        query.setParameter("locationSystem", this.locationSystem.getPeer());
+        query.setParameter("curElevationModel", theCurModel);
+        query.setParameter("range", this.range.getPeer(river));
+
+        final List<BedHeight> bedHeights = query.list();
+        if (bedHeights.isEmpty()) {
+            log.info("Create new BedHeight DB instance.");
+            this.peer = new BedHeight(river, this.year, theType, this.locationSystem.getPeer(), theCurModel,
+                    (this.oldElevationModel != null) ? this.oldElevationModel.getPeer() : null, this.range.getPeer(river),
+                            this.evaluationBy, this.description, this.sounding_width_info, this.comment);
+            session.save(this.peer);
+        }
+        else {
+            this.peer = bedHeights.get(0);
+        }
+
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightValue.java	Tue Apr 03 10:37:30 2018 +0200
+++ b/backend/src/main/java/org/dive4elements/river/importer/ImportBedHeightValue.java	Tue Apr 03 10:40:57 2018 +0200
@@ -11,18 +11,15 @@
 import java.util.List;
 
 import org.apache.log4j.Logger;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
-
 import org.dive4elements.river.model.BedHeight;
 import org.dive4elements.river.model.BedHeightValue;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 public class ImportBedHeightValue {
 
-    private static final Logger log =
-        Logger.getLogger(ImportBedHeightValue.class);
+    private static final Logger log = Logger.getLogger(ImportBedHeightValue.class);
 
 
     protected ImportBedHeight bedHeight;
@@ -32,28 +29,26 @@
     protected Double uncertainty;
     protected Double dataGap;
     protected Double soundingWidth;
+    protected Double minHeight;
+    protected Double maxHeight;
 
     protected BedHeightValue peer;
 
 
-    public ImportBedHeightValue(
-        ImportBedHeight bedHeight,
-        Double station,
-        Double height,
-        Double uncertainty,
-        Double dataGap,
-        Double soundingWidth
-    ) {
+    public ImportBedHeightValue(final ImportBedHeight bedHeight, final Double station, final Double height, final Double uncertainty, final Double dataGap,
+            final Double soundingWidth, final Double minHeight, final Double maxHeight) {
         this.bedHeight     = bedHeight;
         this.station       = station;
         this.height        = height;
         this.uncertainty   = uncertainty;
         this.dataGap       = dataGap;
         this.soundingWidth = soundingWidth;
+        this.minHeight = minHeight;
+        this.maxHeight = maxHeight;
     }
 
 
-    public void storeDependencies(BedHeight bedHeight) {
+    public void storeDependencies(final BedHeight bedHeight) {
         getPeer(bedHeight);
     }
 
@@ -62,37 +57,24 @@
      * Add this value to database or return database bound Value, assuring
      * that the BedHeight exists in db already.
      */
-    public BedHeightValue getPeer(BedHeight bedHeight) {
-        if (peer == null) {
-            Session session = ImporterSession.getInstance()
-                .getDatabaseSession();
-
-            Query query = session.createQuery(
-                "from BedHeightValue where " +
-                "   bedHeight=:bedHeight and " +
-                "   station=:station");
-
-            query.setParameter("bedHeight", bedHeight);
-            query.setParameter("station", station);
+    public BedHeightValue getPeer(final BedHeight bedHeight) {
+        if (this.peer != null)
+            return this.peer;
 
-            List<BedHeightValue> values = query.list();
-            if (values.isEmpty()) {
-                peer = new BedHeightValue(
-                    bedHeight,
-                    station,
-                    height,
-                    uncertainty,
-                    dataGap,
-                    soundingWidth
-                );
-                session.save(peer);
-            }
-            else {
-                peer = values.get(0);
-            }
+        final Session session = ImporterSession.getInstance().getDatabaseSession();
+        final Query query = session.createQuery("FROM BedHeightValue WHERE (bedHeight=:bedHeight)"
+                + " AND (station BETWEEN (:station-0.0001) AND (:station+0.0001))");
+        query.setParameter("bedHeight", bedHeight);
+        query.setParameter("station", this.station);
+        final List<BedHeightValue> values = query.list();
+        if (values.isEmpty()) {
+            this.peer = new BedHeightValue(bedHeight, this.station, this.height, this.uncertainty, this.dataGap, this.soundingWidth,
+                    this.minHeight, this.maxHeight);
+            session.save(this.peer);
+        } else {
+            this.peer = values.get(0);
         }
-
-        return peer;
+        return this.peer;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java	Tue Apr 03 10:37:30 2018 +0200
+++ b/backend/src/main/java/org/dive4elements/river/importer/parsers/BedHeightParser.java	Tue Apr 03 10:40:57 2018 +0200
@@ -9,45 +9,40 @@
 package org.dive4elements.river.importer.parsers;
 
 import java.io.File;
-
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
 import java.math.BigDecimal;
-
 import java.text.NumberFormat;
 import java.text.ParseException;
-
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.EnumMap;
 import java.util.List;
+import java.util.Locale;
 import java.util.TreeSet;
-import java.util.Locale;
-
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import java.io.IOException;
-import java.io.LineNumberReader;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.backend.utils.EpsilonComparator;
 import org.dive4elements.river.importer.ImportBedHeight;
+import org.dive4elements.river.importer.ImportBedHeightType;
 import org.dive4elements.river.importer.ImportBedHeightValue;
-import org.dive4elements.river.importer.ImportBedHeightType;
 import org.dive4elements.river.importer.ImportElevationModel;
 import org.dive4elements.river.importer.ImportLocationSystem;
 import org.dive4elements.river.importer.ImportRange;
 import org.dive4elements.river.importer.ImportTimeInterval;
 import org.dive4elements.river.importer.ImportUnit;
-import org.dive4elements.river.model.BedHeightType;
 import org.dive4elements.river.importer.ImporterSession;
-import org.dive4elements.river.backend.utils.EpsilonComparator;
-import org.dive4elements.river.backend.utils.DateUtil;
+import org.dive4elements.river.model.BedHeightType;
 
 public class BedHeightParser {
 
     private static final Logger log =
-        Logger.getLogger(BedHeightParser.class);
+            Logger.getLogger(BedHeightParser.class);
 
     public static final String ENCODING = "ISO-8859-1";
 
@@ -57,41 +52,65 @@
     public static final String SEPERATOR_CHAR  = ";";
 
     public static final Pattern META_YEAR =
-        Pattern.compile("^Jahr: [^0-9]*(\\d*).*");
+            Pattern.compile("^Jahr: [^0-9]*(\\d*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_TIMEINTERVAL =
-        Pattern.compile("^Zeitraum: Epoche (\\d*)-(\\d*).*");
+            Pattern.compile("^Zeitraum: Epoche (\\d*)-(\\d*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_TYPE =
-        Pattern.compile("^Aufnahmeart: (.*).*");
+            Pattern.compile("^Aufnahmeart: (.*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_LOCATION_SYSTEM =
-        Pattern.compile("^Lagesystem: (.*).*");
+            Pattern.compile("^Lagesystem: (.*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_CUR_ELEVATION_SYSTEM =
-        Pattern.compile("^H.hensystem:\\s(.*)?? \\[(.*)\\].*");
+            Pattern.compile("^H.hensystem:\\s(.*)?? \\[(.*)\\].*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_OLD_ELEVATION_SYSTEM =
-        Pattern.compile("^urspr.ngliches H.hensystem:\\s(.*)?? \\[(.*)\\].*");
+            Pattern.compile("^urspr.ngliches H.hensystem:\\s(.*)?? \\[(.*)\\].*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_RANGE =
-        Pattern.compile("^Strecke:\\D*(\\d++.?\\d*) ?- ?(\\d++.?\\d*).*");
+            Pattern.compile("^Strecke:\\D*(\\d++.?\\d*) ?- ?(\\d++.?\\d*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_EVALUATION_BY =
-        Pattern.compile("^Auswerter: (.*).*");
+            Pattern.compile("^Auswerter: (.*).*", Pattern.CASE_INSENSITIVE);
+
+    public static final Pattern META_SOUNDING_WIDTH = Pattern.compile("^ausgewertete Peilbreite:\\s*(\\S.*).*", Pattern.CASE_INSENSITIVE);
 
     public static final Pattern META_COMMENTS =
-        Pattern.compile("^Weitere Bemerkungen: (.*).*");
+            Pattern.compile("^Weitere Bemerkungen: (.*).*", Pattern.CASE_INSENSITIVE);
 
+    private static final Pattern META_COLUMNTITLES = Pattern.compile("^Fluss-km\\s*;.+", Pattern.CASE_INSENSITIVE);
 
-    protected static NumberFormat nf = NumberFormat.getInstance(
-        DEFAULT_LOCALE);
+    private enum ColTitlePattern {
+        KM("Fluss-km.*"), //
+        HEIGHT("mittlere Sohlh.he\\s*\\[(.*)\\].*"), //
+        UNCERTAINTY("Unsicherheit\\s*\\[(.*)\\].*"), //
+        GAP("Datenl.cke.*"), //
+        WIDTH("Peilbreite\\s*\\[(.*)\\].*"), //
+        MINHEIGHT("Minimale Sohlh.he\\s*\\[(.*)\\].*"), //
+        MAXHEIGHT("Maximale Sohlh.he\\s*\\[(.*)\\].*");
+
+        private final Pattern pattern;
+
+        private ColTitlePattern(final String regexp) {
+            this.pattern = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
+        }
+
+        public Pattern getPattern() {
+            return this.pattern;
+        }
+    }
+
+    private final EnumMap<ColTitlePattern, Integer> cols = new EnumMap<>(ColTitlePattern.class);
+
+    protected static NumberFormat nf = NumberFormat.getInstance(DEFAULT_LOCALE);
 
 
     protected List<ImportBedHeight> bedHeights;
 
 
-    protected ImportBedHeight newImportBedHeight(String description) {
+    protected ImportBedHeight newImportBedHeight(final String description) {
         return new ImportBedHeight(description);
     }
 
@@ -99,30 +118,26 @@
     protected TreeSet<Double> kmExists;
 
     public BedHeightParser() {
-        bedHeights = new ArrayList<ImportBedHeight>();
-        kmExists = new TreeSet<Double>(EpsilonComparator.CMP);
+        this.bedHeights = new ArrayList<>();
+        this.kmExists = new TreeSet<>(EpsilonComparator.CMP);
     }
 
 
     public List<ImportBedHeight> getBedHeights() {
-        return bedHeights;
+        return this.bedHeights;
     }
 
 
-    public void parse(File file) throws IOException {
+    public void parse(final File file) throws IOException {
         log.info("Parsing bed height single file '" + file + "'");
-
-        ImportBedHeight obj = newImportBedHeight(
-            file.getName().replaceAll("\\.csv", ""));
-
-        kmExists.clear();
-
+        final ImportBedHeight obj = newImportBedHeight(file.getName().replaceAll("\\.csv", ""));
+        this.kmExists.clear();
+        this.cols.clear();
+        for (final ColTitlePattern col : ColTitlePattern.values())
+            this.cols.put(col, -1);
         LineNumberReader in = null;
         try {
-            in =
-                new LineNumberReader(
-                new InputStreamReader(
-                new FileInputStream(file), ENCODING));
+            in = new LineNumberReader(new InputStreamReader(new FileInputStream(file), ENCODING));
 
             String line = null;
             while ((line = in.readLine()) != null) {
@@ -139,7 +154,7 @@
             }
 
             log.info("File contained " + obj.getValueCount() + " values.");
-            bedHeights.add(obj);
+            this.bedHeights.add(obj);
         }
         finally {
             if (in != null) {
@@ -149,8 +164,8 @@
     }
 
 
-    protected static String stripMetaLine(String line) {
-        String tmp = line.substring(1, line.length());
+    protected static String stripMetaLine(final String line) {
+        final String tmp = line.substring(1, line.length());
 
         if (tmp.startsWith(" ")) {
             return tmp.substring(1, tmp.length());
@@ -161,8 +176,8 @@
     }
 
 
-    protected void handleMetaLine(ImportBedHeight obj, String line) {
-        String meta = stripMetaLine(line);
+    protected void handleMetaLine(final ImportBedHeight obj, final String line) {
+        final String meta = stripMetaLine(line);
 
         if (handleMetaYear(obj, meta)) {
             return;
@@ -191,17 +206,22 @@
         else if (handleMetaOldElevationModel(obj, meta)) {
             return;
         }
+        else if (handleMetaSoundingWidth(obj, meta)) {
+            return;
+        }
+        else if (handleMetaColumnTitles(obj, meta)) {
+            return;
+        }
         else {
             log.warn("BHP: Meta line did not match any known type: " + line);
         }
     }
 
 
-    protected boolean handleMetaYear(ImportBedHeight obj, String line) {
-        Matcher m = META_YEAR.matcher(line);
-
+    protected boolean handleMetaYear(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_YEAR.matcher(line);
         if (m.matches()) {
-            String tmp = m.group(1);
+            final String tmp = m.group(1).trim();
             if (tmp.length() > 0) {
                 obj.setYear(Integer.parseInt(tmp));
             }
@@ -210,232 +230,190 @@
             }
             return true;
         }
-
-        return false;
-    }
-
-
-    protected boolean handleMetaTimeInterval(
-        ImportBedHeight obj,
-        String line
-    ) {
-        Matcher m = META_TIMEINTERVAL.matcher(line);
-
-        if (m.matches()) {
-            String lo = m.group(1);
-            String up = m.group(2);
-
-            log.debug("Found time interval: " + lo + " - " + up);
-
-            try {
-                int lower = Integer.valueOf(lo);
-                int upper = Integer.valueOf(up);
-
-                Date fromYear = DateUtil.getStartDateFromYear(lower);
-                Date toYear   = DateUtil.getEndDateFromYear(upper);
-
-                obj.setTimeInterval(new ImportTimeInterval(fromYear, toYear));
-            }
-            catch (NumberFormatException e) {
-                log.warn("BHP: could not parse timeinterval", e);
-            }
-
-            return true;
-        }
-
-        return false;
-    }
-
-
-    protected boolean handleMetaComment(ImportBedHeight obj, String line) {
-        Matcher m = META_COMMENTS.matcher(line);
-
-        if (m.matches()) {
-            String tmp = m.group(1);
-
-            obj.setDescription(tmp);
-
-            return true;
-        }
-
         return false;
     }
 
 
-    protected boolean handleMetaEvaluationBy(
-        ImportBedHeight obj,
-        String                line
-    ) {
-        Matcher m = META_EVALUATION_BY.matcher(line);
-
+    protected boolean handleMetaTimeInterval(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_TIMEINTERVAL.matcher(line);
         if (m.matches()) {
-            String tmp = m.group(1);
-            tmp = tmp.replace(";", "");
-
-            obj.setEvaluationBy(tmp);
-
+            final String lo = m.group(1).trim();
+            final String up = m.group(2).trim();
+            log.debug("Found time interval: " + lo + " - " + up);
+            try {
+                final int lower = Integer.valueOf(lo);
+                final int upper = Integer.valueOf(up);
+                final Date fromYear = DateUtil.getStartDateFromYear(lower);
+                final Date toYear   = DateUtil.getEndDateFromYear(upper);
+                obj.setTimeInterval(new ImportTimeInterval(fromYear, toYear));
+            }
+            catch (final NumberFormatException e) {
+                log.warn("BHP: could not parse timeinterval", e);
+            }
             return true;
         }
-
         return false;
     }
 
 
-    protected boolean handleMetaRange(ImportBedHeight obj, String line) {
-        Matcher m = META_RANGE.matcher(line);
-
-        if (m.matches() && m.groupCount() >= 2) {
-            String a = m.group(1).replace(";", "");
-            String b = m.group(2).replace(";", "");
-
-            try {
-                BigDecimal lower = new BigDecimal(nf.parse(a).doubleValue());
-                BigDecimal upper = new BigDecimal(nf.parse(b).doubleValue());
-
-                obj.setRange(new ImportRange(lower, upper));
-
-                return true;
-            }
-            catch (ParseException e) {
-                log.warn("BHP: could not parse range", e);
-            }
+    protected boolean handleMetaComment(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_COMMENTS.matcher(line);
+        if (m.matches()) {
+            final String tmp = m.group(1).replace(SEPERATOR_CHAR, "").trim();
+            obj.setComment(tmp);
+            return true;
         }
-
         return false;
     }
 
 
-    protected boolean handleMetaType(ImportBedHeight obj, String line) {
-        Matcher m = META_TYPE.matcher(line);
-
+    protected boolean handleMetaEvaluationBy(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_EVALUATION_BY.matcher(line);
         if (m.matches()) {
-            String tmp = m.group(1).replace(";", "").trim();
+            final String tmp = m.group(1).replace(";", "").trim();
+            obj.setEvaluationBy(tmp);
+            return true;
+        }
+        return false;
+    }
 
-            BedHeightType bht = BedHeightType.fetchBedHeightTypeForType(
-                tmp,
-                ImporterSession.getInstance().getDatabaseSession());
 
+    protected boolean handleMetaRange(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_RANGE.matcher(line);
+        if (m.matches() && m.groupCount() >= 2) {
+            final String a = m.group(1).replace(";", "").trim();
+            final String b = m.group(2).replace(";", "").trim();
+            try {
+                final BigDecimal lower = new BigDecimal(nf.parse(a).doubleValue());
+                final BigDecimal upper = new BigDecimal(nf.parse(b).doubleValue());
+                obj.setRange(new ImportRange(lower, upper));
+                return true;
+            }
+            catch (final ParseException e) {
+                log.warn("BHP: could not parse range", e);
+            }
+        }
+        return false;
+    }
+
+
+    protected boolean handleMetaType(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_TYPE.matcher(line);
+        if (m.matches()) {
+            final String tmp = m.group(1).replace(";", "").trim();
+            final BedHeightType bht = BedHeightType.fetchBedHeightTypeForType(tmp, ImporterSession.getInstance().getDatabaseSession());
             if (bht != null) {
                 obj.setType(new ImportBedHeightType(bht));
                 return true;
             }
-
             log.error("Unknown bed height type: '" + tmp + "'. File ignored.");
         }
-
-        return false;
-    }
-
-
-    protected boolean handleMetaLocationSystem(
-        ImportBedHeight obj,
-        String          line
-    ) {
-        Matcher m = META_LOCATION_SYSTEM.matcher(line);
-
-        if (m.matches()) {
-            String tmp = m.group(1).replace(";", "");
-
-            obj.setLocationSystem(new ImportLocationSystem(tmp, tmp));
-
-            return true;
-        }
-
-        return false;
-    }
-
-
-    protected boolean handleMetaCurElevationModel(
-        ImportBedHeight obj,
-        String          line
-    ) {
-        Matcher m = META_CUR_ELEVATION_SYSTEM.matcher(line);
-
-        if (m.matches()) {
-            String name = m.group(1);
-            String unit = m.group(2);
-
-            obj.setCurElevationModel(new ImportElevationModel(
-                name,
-                new ImportUnit(unit)
-            ));
-
-            return true;
-        }
-
         return false;
     }
 
 
-    protected boolean handleMetaOldElevationModel(
-        ImportBedHeight obj,
-        String          line
-    ) {
-        Matcher m = META_OLD_ELEVATION_SYSTEM.matcher(line);
-
+    protected boolean handleMetaLocationSystem(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_LOCATION_SYSTEM.matcher(line);
         if (m.matches()) {
-            String name = m.group(1);
-            String unit = m.group(2);
-
-            obj.setOldElevationModel(new ImportElevationModel(
-                name,
-                new ImportUnit(unit)
-            ));
-
+            final String tmp = m.group(1).replace(";", "").trim();
+            obj.setLocationSystem(new ImportLocationSystem(tmp, tmp));
             return true;
         }
-
         return false;
     }
 
-    private Double parse(String []values, int idx, String msg)  {
 
-        if (idx >= 0 && idx < values.length && !values[idx].isEmpty()) {
-            try {
-                return nf.parse(values[idx]).doubleValue();
-            }
-            catch (ParseException e) {
-                log.warn("BSP: unparseable " + msg + " '" + values[idx] + "'");
-            }
+    protected boolean handleMetaCurElevationModel(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_CUR_ELEVATION_SYSTEM.matcher(line);
+        if (m.matches()) {
+            final String name = m.group(1).trim();
+            final String unit = m.group(2).trim();
+            obj.setCurElevationModel(new ImportElevationModel(name, new ImportUnit(unit)));
+            return true;
         }
-
-        return null;
+        return false;
     }
 
-    protected void handleDataLine(ImportBedHeight obj, String line) {
-        String[] values = line.split(SEPERATOR_CHAR, 0);
 
+    protected boolean handleMetaOldElevationModel(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_OLD_ELEVATION_SYSTEM.matcher(line);
+        if (m.matches()) {
+            final String name = m.group(1).trim();
+            final String unit = m.group(2).trim();
+            obj.setOldElevationModel(new ImportElevationModel(name, new ImportUnit(unit)));
+            return true;
+        }
+        return false;
+    }
+
+    protected boolean handleMetaSoundingWidth(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_SOUNDING_WIDTH.matcher(line);
+        if (m.matches()) {
+            final String tmp = m.group(1).replace(SEPERATOR_CHAR, "").trim();
+            obj.setSoundingWidthInfo(tmp);
+            return true;
+        }
+        return false;
+    }
+
+
+    /**
+     * Tries to parse a line as column titles line
+     */
+    protected boolean handleMetaColumnTitles(final ImportBedHeight obj, final String line) {
+        final Matcher m = META_COLUMNTITLES.matcher(line);
+        if (m.matches()) {
+            final Matcher cm;
+            final String[] titles = line.split(SEPERATOR_CHAR, 0);
+            for (int i = 0; i <= titles.length - 1; i++) {
+                for (final ColTitlePattern col : ColTitlePattern.values()) {
+                    if (col.getPattern().matcher(titles[i]).matches()) {
+                        this.cols.put(col, i);
+                        break;
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    protected void handleDataLine(final ImportBedHeight obj, final String line) {
+        final String[] values = line.split(SEPERATOR_CHAR, 0);
         if (values.length < 2) {
             // Do not import line without data or only km
             return;
         }
-
         Double km;
         try {
             km = new Double(nf.parse(values[0]).doubleValue());
-
-            if (kmExists.contains(km)) {
-                log.warn("duplicate station '" + km + "': -> ignored");
+            if (this.kmExists.contains(km)) {
+                log.warn("duplicate station '" + values[0] + "': -> ignored");
                 return;
             }
-
-            kmExists.add(km);
+            this.kmExists.add(km);
         }
-        catch (ParseException e) {
-            log.error("Error parsing km '" + values[0] + "': " +
-                e.getMessage());
+        catch (final ParseException e) {
+            log.error("Error parsing km '" + values[0] + "': " + e.getMessage());
             return;
         }
-
-        ImportBedHeightValue value = new ImportBedHeightValue(
-            (ImportBedHeight) obj,
-            km,
-            parse(values, 1, "height"),
-            parse(values, 2, "uncertainty"),
-            parse(values, 3, "data gap"),
-            parse(values, 4, "sounding width"));
+        final ImportBedHeightValue value = new ImportBedHeightValue(obj, km, parse(values, ColTitlePattern.HEIGHT),
+                parse(values, ColTitlePattern.UNCERTAINTY), parse(values, ColTitlePattern.GAP), parse(values, ColTitlePattern.WIDTH),
+                parse(values, ColTitlePattern.MINHEIGHT), parse(values, ColTitlePattern.MAXHEIGHT));
 
         obj.addValue(value);
     }
+
+    private Double parse(final String[] values, final ColTitlePattern col) {
+        final int idx = this.cols.get(col).intValue();
+        if ((idx >= 0) && (idx < values.length) && !values[idx].trim().isEmpty()) {
+            try {
+                return nf.parse(values[idx]).doubleValue();
+            }
+            catch (final ParseException e) {
+                log.warn("unparseable " + col.toString() + " '" + values[idx] + "'");
+            }
+        }
+        return null;
+    }
 }
-// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/backend/src/main/java/org/dive4elements/river/model/BedHeight.java	Tue Apr 03 10:37:30 2018 +0200
+++ b/backend/src/main/java/org/dive4elements/river/model/BedHeight.java	Tue Apr 03 10:40:57 2018 +0200
@@ -9,25 +9,23 @@
 package org.dive4elements.river.model;
 
 import java.io.Serializable;
-
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
 import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
-import javax.persistence.JoinColumn;
-import javax.persistence.OneToOne;
-import javax.persistence.OneToMany;
-
-import org.hibernate.Session;
-import org.hibernate.Query;
+import javax.persistence.Table;
 
 import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
+import org.hibernate.Session;
 
 
 @Entity
@@ -52,6 +50,9 @@
 
     private Range range;
 
+    private String sounding_width_info;
+    private String comment;
+
     private List<BedHeightValue> values;
 
 
@@ -59,38 +60,17 @@
     }
 
 
-    public BedHeight(
-        River          river,
-        Integer        year,
-        BedHeightType  type,
-        LocationSystem locationSystem,
-        ElevationModel curElevationModel,
-        Range          range
-    ) {
-        this(
-            river,
-            year,
-            type,
-            locationSystem,
-            curElevationModel,
-            null,
-            range,
-            null,
-            null);
+    public BedHeight(final River river, final Integer year, final BedHeightType type, final LocationSystem locationSystem,
+            final ElevationModel curElevationModel,
+            final Range range) {
+        this(river, year, type, locationSystem, curElevationModel, null, range, null, null, null, null);
     }
 
 
-    public BedHeight(
-        River          river,
-        Integer        year,
-        BedHeightType  type,
-        LocationSystem locationSystem,
-        ElevationModel curElevationModel,
-        ElevationModel oldElevationModel,
-        Range          range,
-        String         evaluationBy,
-        String         description
-    ) {
+    public BedHeight(final River river, final Integer year, final BedHeightType type, final LocationSystem locationSystem,
+            final ElevationModel curElevationModel,
+            final ElevationModel oldElevationModel, final Range range, final String evaluationBy, final String description, final String sounding_width_info,
+            final String comment) {
         this.river             = river;
         this.year              = year;
         this.type              = type;
@@ -100,144 +80,159 @@
         this.range             = range;
         this.evaluationBy      = evaluationBy;
         this.description       = description;
+        this.sounding_width_info = sounding_width_info;
+        this.comment = comment;
     }
 
 
     @Id
-    @SequenceGenerator(
-        name           = "SEQUENCE_BED_HEIGHT_ID_SEQ",
-        sequenceName   = "BED_HEIGHT_ID_SEQ",
-        allocationSize = 1)
-    @GeneratedValue(
-        strategy  = GenerationType.SEQUENCE,
-        generator = "SEQUENCE_BED_HEIGHT_ID_SEQ")
+    @SequenceGenerator(name = "SEQUENCE_BED_HEIGHT_ID_SEQ", sequenceName = "BED_HEIGHT_ID_SEQ", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQUENCE_BED_HEIGHT_ID_SEQ")
     @Column(name = "id")
     public Integer getId() {
-        return id;
+        return this.id;
     }
 
-    public void setId(Integer id) {
+    public void setId(final Integer id) {
         this.id = id;
     }
 
     @OneToOne
     @JoinColumn(name = "river_id")
     public River getRiver() {
-        return river;
+        return this.river;
     }
 
-    public void setRiver(River river) {
+    public void setRiver(final River river) {
         this.river = river;
     }
 
     @Column(name = "year")
     public Integer getYear() {
-        return year;
+        return this.year;
     }
 
-    public void setYear(Integer year) {
+    public void setYear(final Integer year) {
         this.year = year;
     }
 
     @OneToOne
     @JoinColumn(name = "type_id")
     public BedHeightType getType() {
-        return type;
+        return this.type;
     }
 
-    public void setType(BedHeightType type) {
+    public void setType(final BedHeightType type) {
         this.type = type;
     }
 
     @OneToOne
     @JoinColumn(name = "location_system_id")
     public LocationSystem getLocationSystem() {
-        return locationSystem;
+        return this.locationSystem;
     }
 
-    public void setLocationSystem(LocationSystem locationSystem) {
+    public void setLocationSystem(final LocationSystem locationSystem) {
         this.locationSystem = locationSystem;
     }
 
     @OneToOne
     @JoinColumn(name = "cur_elevation_model_id")
     public ElevationModel getCurElevationModel() {
-        return curElevationModel;
+        return this.curElevationModel;
     }
 
-    public void setCurElevationModel(ElevationModel curElevationModel) {
+    public void setCurElevationModel(final ElevationModel curElevationModel) {
         this.curElevationModel = curElevationModel;
     }
 
     @OneToOne
     @JoinColumn(name = "old_elevation_model_id")
     public ElevationModel getOldElevationModel() {
-        return oldElevationModel;
+        return this.oldElevationModel;
     }
 
-    public void setOldElevationModel(ElevationModel oldElevationModel) {
+    public void setOldElevationModel(final ElevationModel oldElevationModel) {
         this.oldElevationModel = oldElevationModel;
     }
 
     @OneToOne
     @JoinColumn(name = "range_id")
     public Range getRange() {
-        return range;
+        return this.range;
     }
 
-    public void setRange(Range range) {
+    public void setRange(final Range range) {
         this.range = range;
     }
 
     @Column(name = "evaluation_by")
     public String getEvaluationBy() {
-        return evaluationBy;
+        return this.evaluationBy;
     }
 
-    public void setEvaluationBy(String evaluationBy) {
+    public void setEvaluationBy(final String evaluationBy) {
         this.evaluationBy = evaluationBy;
     }
 
     @Column(name = "description")
     public String getDescription() {
-        return description;
+        return this.description;
     }
 
-    public void setDescription(String description) {
+    public void setDescription(final String description) {
         this.description = description;
     }
 
+    @Column(name = "sounding_width_info")
+    public String getSoundingWidthInfo() {
+        return this.sounding_width_info;
+    }
+
+    public void setSoundingWidthInfo(final String sounding_width_info) {
+        this.sounding_width_info = sounding_width_info;
+    }
+
+    @Column(name = "comment")
+    public String getComment() {
+        return this.comment;
+    }
+
+    public void setComment(final String comment) {
+        this.comment = comment;
+    }
+
     @OneToMany
     @JoinColumn(name = "bed_height_id")
     public List<BedHeightValue> getValues() {
-        return values;
+        return this.values;
     }
 
-    public void setValues(List<BedHeightValue> values) {
+    public void setValues(final List<BedHeightValue> values) {
         this.values = values;
     }
 
 
     public static List<BedHeight> getBedHeights(
-        River  river,
-        double kmLo,
-        double kmHi
-    ) {
-        Session session = SessionHolder.HOLDER.get();
+            final River  river,
+            final double kmLo,
+            final double kmHi
+            ) {
+        final Session session = SessionHolder.HOLDER.get();
 
-        Query query = session.createQuery(
-            "from BedHeight where river=:river");
+        final Query query = session.createQuery(
+                "from BedHeight where river=:river");
 
         query.setParameter("river", river);
 
         // TODO Do km range filtering in SQL statement
 
-        List<BedHeight> singles = query.list();
-        List<BedHeight> good    = new ArrayList<BedHeight>();
+        final List<BedHeight> singles = query.list();
+        final List<BedHeight> good    = new ArrayList<>();
 
-        for (BedHeight s: singles) {
-            for (BedHeightValue value: s.getValues()) {
-                double station = value.getStation().doubleValue();
+        for (final BedHeight s: singles) {
+            for (final BedHeightValue value: s.getValues()) {
+                final double station = value.getStation().doubleValue();
 
                 if (station >= kmLo && station <= kmHi) {
                     good.add(s);
@@ -250,29 +245,29 @@
     }
 
 
-    public static BedHeight getBedHeightById(int id) {
-        Session session = SessionHolder.HOLDER.get();
+    public static BedHeight getBedHeightById(final int id) {
+        final Session session = SessionHolder.HOLDER.get();
 
-        Query query = session.createQuery(
-            "from BedHeight where id=:id");
+        final Query query = session.createQuery(
+                "from BedHeight where id=:id");
 
         query.setParameter("id", id);
 
-        List<BedHeight> singles = query.list();
+        final List<BedHeight> singles = query.list();
 
         return singles != null ? singles.get(0) : null;
     }
 
     public static BedHeight getBedHeightByDescription(final String description) {
-        
+
         final Session session = SessionHolder.HOLDER.get();
-        
-        final Query query = session.createQuery("from BedHeight where description=:description");
+
+        final Query query = session.createQuery("FROM BedHeight WHERE (trim(description)=:description)");
         query.setParameter("description", description);
-        
+
         final List<BedHeight> singles = query.list();
-        
-        return singles != null ? singles.get(0) : null;        
+
+        return singles != null ? singles.get(0) : null;
     }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
\ No newline at end of file
--- a/backend/src/main/java/org/dive4elements/river/model/BedHeightValue.java	Tue Apr 03 10:37:30 2018 +0200
+++ b/backend/src/main/java/org/dive4elements/river/model/BedHeightValue.java	Tue Apr 03 10:40:57 2018 +0200
@@ -8,26 +8,23 @@
 
 package org.dive4elements.river.model;
 
+import java.io.Serializable;
 import java.util.List;
 
-import java.io.Serializable;
-
+import javax.persistence.Column;
 import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
 import javax.persistence.Id;
-import javax.persistence.Table;
-import javax.persistence.GeneratedValue;
-import javax.persistence.Column;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.GenerationType;
 import javax.persistence.JoinColumn;
 import javax.persistence.OneToOne;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
 
 import org.apache.log4j.Logger;
-
+import org.dive4elements.river.backend.SessionHolder;
+import org.hibernate.Query;
 import org.hibernate.Session;
-import org.hibernate.Query;
-
-import org.dive4elements.river.backend.SessionHolder;
 
 
 @Entity
@@ -36,7 +33,7 @@
 implements   Serializable
 {
     private static Logger log =
-        Logger.getLogger(BedHeightValue.class);
+            Logger.getLogger(BedHeightValue.class);
 
     private Integer id;
 
@@ -151,34 +148,21 @@
         this.maxHeight = maxHeight;
     }
 
-
-    public static List<BedHeightValue> getBedHeightValues(
-        BedHeight single) {
-        Session session = SessionHolder.HOLDER.get();
-
-        Query query = session.createQuery(
-            "from BedHeightValue where bedHeight=:single");
-
+    public static List<BedHeightValue> getBedHeightValues(final BedHeight single) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM BedHeightValue WHERE bedHeight=:single");
         query.setParameter("single", single);
         return query.list();
     }
 
 
-    public static List<BedHeightValue> getBedHeightValues(
-        BedHeight single,
-        double kmLo,
-        double kmHi
-    ) {
-        Session session = SessionHolder.HOLDER.get();
-
-        Query query = session.createQuery(
-            "from BedHeightValue where bedHeight=:single " +
-            "   and station >= :kmLo and station <= :kmHi");
-
+    public static List<BedHeightValue> getBedHeightValues(final BedHeight single, final double kmLo, final double kmHi) {
+        final Session session = SessionHolder.HOLDER.get();
+        final Query query = session.createQuery("FROM BedHeightValue WHERE (bedHeight=:single)"
+                + " AND (station >= :kmLo) AND (station <= :kmHi)");
         query.setParameter("single", single);
         query.setParameter("kmLo", new Double(kmLo));
         query.setParameter("kmHi", new Double(kmHi));
-
         return query.list();
     }
 }

http://dive4elements.wald.intevation.org