Java tutorial
/*---------------- FILE HEADER KALYPSO ------------------------------------------ * * This file is part of kalypso. * Copyright (C) 2004 by: * * Technical University Hamburg-Harburg (TUHH) * Institute of River and coastal engineering * Denickestrae 22 * 21073 Hamburg, Germany * http://www.tuhh.de/wb * * and * * Bjoernsen Consulting Engineers (BCE) * Maria Trost 3 * 56070 Koblenz, Germany * http://www.bjoernsen.de * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: * * E-Mail: * belger@bjoernsen.de * schlienger@bjoernsen.de * v.doemming@tuhh.de * * ---------------------------------------------------------------------------*/ package org.kalypso.model.wspm.pdb.ui.internal.gaf; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Set; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.kalypso.model.wspm.pdb.db.mapping.CrossSection; import org.kalypso.model.wspm.pdb.db.mapping.CrossSectionPart; import org.kalypso.model.wspm.pdb.db.mapping.CrossSectionPartType; import org.kalypso.model.wspm.pdb.db.mapping.Point; import org.kalypso.model.wspm.pdb.db.mapping.Roughness; import org.kalypso.model.wspm.pdb.db.mapping.Vegetation; import org.kalypso.model.wspm.pdb.db.utils.ByCategoryComparator; import org.kalypso.model.wspm.pdb.db.utils.ByStationComparator; import org.kalypso.model.wspm.pdb.db.utils.ConsecutiveNumComparator; import org.kalypso.model.wspm.pdb.gaf.GafCode; import org.kalypso.model.wspm.pdb.gaf.GafCodes; import org.kalypso.model.wspm.pdb.gaf.GafKind; import org.kalypso.model.wspm.pdb.gaf.IGafConstants; import org.kalypso.model.wspm.pdb.ui.internal.WspmPdbUiPlugin; import org.kalypso.model.wspm.pdb.ui.internal.i18n.Messages; /** * This writer serializes profile data into the gaf format. * * @author Holger Albert */ public class GafWriter { private final String GAF_LINE = "%.3f\t%s\t%s\t%s\t%s\t%d\t%d\t%s\t%s\t%s"; //$NON-NLS-1$ // TODO: maybe get as option private static final String EMPTY_HYK_CODE = "x"; //$NON-NLS-1$ private final HykExportMode m_hykExportMode; private final GafCodes m_codes; /** Stores the lines with multiple hyk entries */ private final List<String> m_additionalLines = new ArrayList<>(); public GafWriter(final GafCodes codes, final HykExportMode hykExportMode) { m_codes = codes; m_hykExportMode = hykExportMode; } /** * This function writes the cross sections to the file. * * @param crossSections * The cross sections. * @param file * The file. * @param monitor * A progress monitor. * @return A status, indicating the result of the operation. */ public IStatus write(final Set<CrossSection> crossSections, final File file, final IProgressMonitor monitor) { PrintWriter writer = null; try { writer = new PrintWriter(file); /* Monitor. */ monitor.beginTask(Messages.getString("GafWriter_0"), 100 * crossSections.size()); //$NON-NLS-1$ monitor.subTask(Messages.getString("GafWriter_1")); //$NON-NLS-1$ /* Sort the cross sections. */ final CrossSection[] sortedCrossSections = crossSections.toArray(new CrossSection[] {}); Arrays.sort(sortedCrossSections, new ByStationComparator()); /* Loop the cross sections. */ for (final CrossSection crossSection : sortedCrossSections) { /* Write the cross section. */ writeCrossSection(crossSection, writer); /* Monitor. */ monitor.worked(100); } /* write additional lines in separate file */ writeAdditionalLines(file); return new Status(IStatus.OK, WspmPdbUiPlugin.PLUGIN_ID, Messages.getString("GafWriter_2")); //$NON-NLS-1$ } catch (final Exception ex) { return new Status(IStatus.ERROR, WspmPdbUiPlugin.PLUGIN_ID, String.format(Messages.getString("GafWriter_3"), ex.getLocalizedMessage()), ex); //$NON-NLS-1$ } finally { /* Close the writer. */ IOUtils.closeQuietly(writer); /* Monitor. */ monitor.done(); } } private void writeAdditionalLines(final File gafFile) throws IOException { if (m_additionalLines.isEmpty()) return; final String hykFilePath = gafFile.getAbsolutePath() + ".hyk"; //$NON-NLS-1$ final File hykFile = new File(hykFilePath); FileUtils.writeLines(hykFile, m_additionalLines); } private void writeCrossSection(final CrossSection crossSection, final PrintWriter writer) { /* Get the cross section parts. */ final Set<CrossSectionPart> parts = crossSection.getCrossSectionParts(); /* Sort the cross sections. */ final CrossSectionPart[] sortedParts = parts.toArray(new CrossSectionPart[] {}); Arrays.sort(sortedParts, new ByCategoryComparator()); /* Loop the cross section parts. */ for (final CrossSectionPart part : sortedParts) { /* Write the cross section part. */ writeCrossSectionPart(part, writer); } } private void writeCrossSectionPart(final CrossSectionPart part, final PrintWriter writer) { /* Get the points. */ final Set<Point> points = part.getPoints(); /* Sort the points. */ final Point[] sortedPoints = points.toArray(new Point[] {}); Arrays.sort(sortedPoints, new ConsecutiveNumComparator()); final CrossSectionPartType partType = part.getCrossSectionPartType(); final GafKind kind = findKind(partType); /* Loop the points. */ for (final Point point : sortedPoints) { /* Write the point. */ writePoint(kind, point, writer); } } private GafKind findKind(final CrossSectionPartType partType) { if (partType == null) return GafKind.P; try { final String category = partType.getCategory(); return GafKind.valueOf(category); } catch (final Exception e) { // ignore return GafKind.P; } } private void writePoint(final GafKind kind, final Point point, final PrintWriter writer) { /* Get the data to write. */ final CrossSection crossSection = point.getCrossSectionPart().getCrossSection(); final double station = crossSection.getStation().doubleValue(); final String id = point.getName(); String y = "-1"; //$NON-NLS-1$ final BigDecimal width = point.getWidth(); if (width != null) y = String.format("%.4f", width.doubleValue()); //$NON-NLS-1$ String z = "-1"; //$NON-NLS-1$ final BigDecimal height = point.getHeight(); if (height != null) z = String.format("%.4f", height.doubleValue()); //$NON-NLS-1$ final Roughness roughness = point.getRoughness(); final Vegetation vegetation = point.getVegetation(); final int rk = Integer.parseInt(roughness.getId().getName()); final int bk = Integer.parseInt(vegetation.getId().getName()); /* geo location */ final com.vividsolutions.jts.geom.Point location = point.getLocation(); final Double hw = location == null ? null : location.getY(); final Double rw = location == null ? null : location.getX(); final String hwStr = hw == null ? StringUtils.EMPTY : String.format("%.4f", hw); //$NON-NLS-1$ final String rwStr = rw == null ? StringUtils.EMPTY : String.format("%.4f", rw); //$NON-NLS-1$ final String code = point.getCode(); final String hyk = StringUtils.isBlank(point.getHyk()) ? EMPTY_HYK_CODE : point.getHyk(); /* the gaf writer might produce multiple hyk codes, we need to write one line per single code */ final String[] hyks = StringUtils.split(hyk, IGafConstants.HYK_CODE_SEPARATOR); /* depending on the export mode, the code/hyk gets tweaked; first tweak than count lines, because tweak may reduce codes to normal lines */ final Pair<String, String>[] tweakedCodes = tweakHyks(kind, code, hyks); int count = 0; for (final Pair<String, String> tweakedPair : tweakedCodes) { final String tweakedCode = tweakedPair.getLeft(); final String tweakedHyk = tweakedPair.getRight(); final String line = String.format(Locale.PRC, GAF_LINE, station, id, y, z, tweakedCode, rk, bk, hwStr, rwStr, tweakedHyk); // REMARK: store first line in file, additional hyk lines are stored in separate file // IMPORTANT: order of lines is given by order of hyk codes made by the PPPartBuilder (PA,PE, LU,RU, LBOK,RBOK) if (count++ == 0) writer.append(line).println(); else m_additionalLines.add(line); } } private Pair<String, String>[] tweakHyks(final GafKind kind, final String code, final String[] hyks) { /* depending on mode, the tweaked codes can be mapped to repeatedly non-hyk-codes; so we use a set to eleminate duplicates */ final Collection<Pair<String, String>> pairs = new LinkedHashSet<>(); for (final String hyk : hyks) { final String tweakedCode = tweakCode(kind, code, hyk); final String tweakedHyk = tweakHyk(code, hyk); pairs.add(Pair.of(tweakedCode, tweakedHyk)); } return pairs.toArray(new Pair[pairs.size()]); } private String tweakCode(final GafKind kind, final String code, final String hyk) { switch (m_hykExportMode) { case CODE: return code; case MARKER: /* use markers code if set, else delete existing hyk codes from code and fall back to default */ if (hyk != EMPTY_HYK_CODE) return hyk; else if (isHykCode(code)) return m_codes.getDefaultCode(kind).getCode(); else return code; default: throw new IllegalStateException(); } } private String tweakHyk(final String code, final String hyk) { switch (m_hykExportMode) { case CODE: if (isHykCode(code)) return code; else return EMPTY_HYK_CODE; case MARKER: return hyk; default: throw new IllegalStateException(); } } private boolean isHykCode(final String code) { final GafCode gafCode = m_codes.getCode(code); if (gafCode == null) return false; final String hyk = gafCode.getHyk(); if (StringUtils.isEmpty(hyk)) return false; return true; } }