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.tuhh.core.wspwin; import java.io.File; import java.io.IOException; import java.io.OutputStreamWriter; import java.math.BigDecimal; import java.net.URL; import java.nio.charset.Charset; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.kalypso.commons.resources.SetContentHelper; import org.kalypso.contribs.eclipse.core.resources.ResourceUtilities; import org.kalypso.contribs.eclipse.core.runtime.IStatusCollector; import org.kalypso.contribs.eclipse.core.runtime.StatusCollector; import org.kalypso.gmlschema.GMLSchemaException; import org.kalypso.model.wspm.core.KalypsoModelWspmCoreExtensions; import org.kalypso.model.wspm.core.gml.IProfileFeature; import org.kalypso.model.wspm.core.gml.IRunOffEvent; import org.kalypso.model.wspm.core.gml.ProfileFeatureBinding; import org.kalypso.model.wspm.core.gml.WspmFixation; import org.kalypso.model.wspm.core.gml.WspmProject; import org.kalypso.model.wspm.core.gml.WspmWaterBody; import org.kalypso.model.wspm.core.profil.IProfile; import org.kalypso.model.wspm.core.profil.serializer.IProfileSource; import org.kalypso.model.wspm.core.profil.serializer.ProfileSerializerUtilitites; import org.kalypso.model.wspm.tuhh.core.IWspmTuhhConstants; import org.kalypso.model.wspm.tuhh.core.KalypsoModelWspmTuhhCorePlugin; import org.kalypso.model.wspm.tuhh.core.gml.TuhhReach; import org.kalypso.model.wspm.tuhh.core.gml.TuhhWspmProject; import org.kalypso.model.wspm.tuhh.core.i18n.Messages; import org.kalypso.model.wspm.tuhh.core.profile.energyloss.Energyloss; import org.kalypso.model.wspm.tuhh.core.profile.energyloss.EnergylossProfileObject; import org.kalypso.observation.IObservation; import org.kalypso.observation.result.IRecord; import org.kalypso.observation.result.TupleResult; import org.kalypso.ogc.gml.om.IObservationFeature; import org.kalypso.ogc.gml.serialize.GmlSerializer; import org.kalypso.wspwin.core.CalculationBean; import org.kalypso.wspwin.core.ICalculationContentBean; import org.kalypso.wspwin.core.LocalEnergyLossBean; import org.kalypso.wspwin.core.ProfileBean; import org.kalypso.wspwin.core.RunOffEventBean; import org.kalypso.wspwin.core.WspCfg; import org.kalypso.wspwin.core.WspCfg.TYPE; import org.kalypso.wspwin.core.WspWinProject; import org.kalypso.wspwin.core.WspWinZustand; import org.kalypso.wspwin.core.ZustandBean; import org.kalypso.wspwin.core.ZustandSegmentBean; import org.kalypsodeegree.model.feature.Feature; import org.kalypsodeegree.model.feature.GMLWorkspace; import org.kalypsodeegree.model.feature.IFeatureBindingCollection; /** * @author thuel2 */ public final class WspWinImporter { private static final DateFormat DATE_FORMATTER = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT); private WspWinImporter() { } /** * Imports a wpswin project into a folder or a project. * <p> * Prerequisite: container holds a valid wspm-tuhh structure * </p> */ public static IStatus importProject(final File wspwinDirectory, final IContainer targetContainer, final IProgressMonitor monitor) throws Exception { final IStatusCollector logStatus = new StatusCollector(KalypsoModelWspmTuhhCorePlugin.PLUGIN_ID); final String problemMessage = Messages .getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.1"); //$NON-NLS-1$ monitor.beginTask(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.2"), 1000); //$NON-NLS-1$ monitor.subTask(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.3")); //$NON-NLS-1$ try { final WspWinProject wspWinProject = new WspWinProject(wspwinDirectory); // load gml workspace monitor.subTask(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.4")); //$NON-NLS-1$ final IFile modelFile = targetContainer.getFile(new Path("modell.gml")); //$NON-NLS-1$ final URL url = ResourceUtilities.createURL(modelFile); final GMLWorkspace workspace = GmlSerializer.createGMLWorkspace(url, null); monitor.worked(200); monitor.subTask(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.6")); //$NON-NLS-1$ // load wspwin data monitor.subTask(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.7")); //$NON-NLS-1$ // fill wspwin data into workspace final Feature modelRootFeature = workspace.getRootFeature(); final WspmProject wspmProject = (WspmProject) modelRootFeature; // ////////////// // // set model name // // ////////////// // final String oldProjectName = wspmProject.getName(); final String modelName = oldProjectName + wspwinDirectory.getName(); wspmProject.setName(modelName); // ///////////////////// // // set model description // // ///////////////////// // final String oldProjectDescription = wspmProject.getDescription(); final StringBuffer modelDescription = new StringBuffer( oldProjectDescription == null ? "" : oldProjectDescription); //$NON-NLS-1$ if (modelDescription.length() != 0) { modelDescription.append("\n\n"); //$NON-NLS-1$ } final String description = Messages.getString( "org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.10", wspwinDirectory.getAbsolutePath(), //$NON-NLS-1$ DATE_FORMATTER.format(new Date(System.currentTimeMillis()))); modelDescription.append(description); final String wspwinModelDescription = readProjectDescription(wspWinProject); if (wspwinModelDescription != null) { modelDescription .append(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.13")); //$NON-NLS-1$ modelDescription.append(wspwinModelDescription); } wspmProject.setDescription(modelDescription.toString()); // /////////////////// // // Load WspWin Project // // /////////////////// // final WspCfg wspCfgBean = new WspCfg(wspWinProject, StringUtils.EMPTY); final IStatus wspCfgStatus = wspCfgBean.read(); logStatus.add(wspCfgStatus); // from now on, we have tuhh projects: if we later support other kinds of projects, tweak here final TuhhWspmProject tuhhProject = (TuhhWspmProject) modelRootFeature; // TODO: ask direction from user final boolean isDirectionUpstreams = true; // /////////////// // // import profiles // // /////////////// // final Map<String, IProfileFeature> importedProfiles = new HashMap<>(); final ProfileBean[] commonProfiles = wspCfgBean.getProfiles(); final File profDir = wspWinProject.getProfDir(); logStatus.add( importProfiles(profDir, tuhhProject, commonProfiles, importedProfiles, isDirectionUpstreams)); // ////////////// // // import reaches // // ////////////// // final WspWinZustand[] zustaende = wspCfgBean.getZustaende(); for (final WspWinZustand zustand : zustaende) { try { logStatus.add(importTuhhZustand(tuhhProject, wspCfgBean, zustand, importedProfiles, isDirectionUpstreams, targetContainer)); } catch (final Exception e) { final String fileName = zustand.getBean().getFileName(); logStatus.add(IStatus.ERROR, Messages .getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.16", fileName), e); //$NON-NLS-1$ } } // stop, if we have errors until now final IStatus tmpStatus = logStatus.asMultiStatus(problemMessage); if (tmpStatus.matches(IStatus.ERROR | IStatus.CANCEL)) return tmpStatus; // /////////////// // // write workspace // // /////////////// // monitor.subTask(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.17")); //$NON-NLS-1$ final SetContentHelper contentHelper = new SetContentHelper() { @Override protected void write(final OutputStreamWriter writer) throws Throwable { GmlSerializer.serializeWorkspace(writer, workspace); } }; contentHelper.setFileContents(modelFile, false, true, new SubProgressMonitor(monitor, 200)); } finally { monitor.done(); } final MultiStatus completeStatus = logStatus.asMultiStatus(problemMessage); if (completeStatus.isOK()) { final String okMessage = Messages .getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.29"); //$NON-NLS-1$ return logStatus.asMultiStatus(okMessage); } return completeStatus; } /** * Adds the profile beans as profiles to the tuhh-project. For each profile bean, a new profile file is generated and * the profile is added as reference to it. */ private static IStatus importProfiles(final File profDir, final TuhhWspmProject tuhhProject, final ProfileBean[] commonProfiles, final Map<String, IProfileFeature> addedProfiles, final boolean isDirectionUpstreams) { final IStatusCollector log = new StatusCollector(KalypsoModelWspmTuhhCorePlugin.PLUGIN_ID); for (final ProfileBean bean : commonProfiles) { try { final IProfileFeature profile = importProfile(profDir, tuhhProject, addedProfiles, bean, isDirectionUpstreams, true); if (profile != null) { final BigDecimal profStation = profile.getBigStation(); final BigDecimal beanStation = bean.getStation(); // if( Math.abs( profStation.doubleValue() - beanStation.doubleValue() ) > 0.0001 ) if (profStation.compareTo(beanStation) != 0) { final BigDecimal fixedStation = fixStation(profStation, beanStation); final String msg = Messages.getString( "org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.19", bean.getFileName(), //$NON-NLS-1$ profStation, bean.getWaterName(), bean.getStateName(), beanStation); log.add(IStatus.INFO, msg); // FIXME: bad: probably the station of the profproj.txt is rounded, so we are using the worse number here. // We should instead use the station with the most significant digits. profile.setBigStation(fixedStation); } } } catch (final IOException e) { final String msg = Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.119", //$NON-NLS-1$ bean.getFileName()); log.add(IStatus.INFO, msg, e); } catch (final GMLSchemaException e) { log.add(IStatus.ERROR, e.getLocalizedMessage(), e); } catch (final CoreException e) { log.add(e.getStatus()); } } final String okMessage = Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.120");//$NON-NLS-1$ return log.asMultiStatusOrOK(okMessage, okMessage); } /** * Returns the station with the most significant decimals. */ private static BigDecimal fixStation(final BigDecimal profStation, final BigDecimal beanStation) { final int profScale = profStation.scale(); final int beanScale = beanStation.scale(); if (profScale > beanScale) return profStation; else return beanStation; } /** * Imports a single profile according to the given ProfileBean. If the map already contains a profile with the same id * (usually the filename), we return this instead. */ private static IProfileFeature importProfile(final File profDir, final TuhhWspmProject tuhhProject, final Map<String, IProfileFeature> knownProfiles, final ProfileBean bean, final boolean isDirectionUpstreams, final boolean ignoreMissingFile) throws GMLSchemaException, IOException, CoreException { final String fileName = bean.getFileName(); if (knownProfiles.containsKey(fileName)) return knownProfiles.get(fileName); final IProfileFeature prof = tuhhProject.createNewProfile(bean.getWaterName(), isDirectionUpstreams); final File prfFile = new File(profDir, fileName); if (!prfFile.exists()) { if (ignoreMissingFile) { // REMARK: this is a situation that occurs rather often, because WspWin does not correctly keep // track of removed profiles (i.e. if a profile is removed from its strand, the profile is not removed // from the profproj file. Because of this, we silently ignore htis problem. return null; } else { // REMARK: if file is missing and referenced from a strand, we really have a problem. final String message = String.format(Messages.getString("WspWinImporter.0"), fileName); //$NON-NLS-1$ final IStatus status = new Status(IStatus.WARNING, KalypsoModelWspmTuhhCorePlugin.PLUGIN_ID, message); throw new CoreException(status); } } final String profiletype = IWspmTuhhConstants.PROFIL_TYPE_PASCHE; final IProfileSource prfSource = KalypsoModelWspmCoreExtensions.createProfilSource("prf"); //$NON-NLS-1$ final IProfile[] profile = ProfileSerializerUtilitites.readProfile(prfSource, prfFile, profiletype); ((ProfileFeatureBinding) prof).setProfile(profile[0]); /* Set filename as profile name in order to make it unique */ prof.setName(FilenameUtils.removeExtension(fileName)); /* Set state as default description for profile. */ prof.setDescription(bean.getStateName()); /* Only add profile if no error occurs */ knownProfiles.put(fileName, prof); return prof; } /** * Adds the zustand-bean to the tuhh-project. Already imported profiles are not imported a second time. * <p> * If the zustand contains unknown profiles (e.g. due to a wspwin bug), they will be also imported and added to the importedPRofilesMap. * </p> */ private static IStatus importTuhhZustand(final TuhhWspmProject tuhhProject, final WspCfg wspCfg, final WspWinZustand zustand, final Map<String, IProfileFeature> importedProfiles, final boolean isDirectionUpstreams, final IContainer targetContainer) throws GMLSchemaException { final ZustandBean zustandBean = zustand.getBean(); final String message = Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.21", //$NON-NLS-1$ zustandBean.getFileName()); final IStatusCollector log = new StatusCollector(KalypsoModelWspmTuhhCorePlugin.PLUGIN_ID); final String name = zustandBean.getName(); final String waterName = zustandBean.getWaterName(); final TuhhReach reach = tuhhProject.createNewReach(waterName, isDirectionUpstreams); reach.setName(name); final StringBuffer descBuffer = new StringBuffer(); descBuffer.append(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.22")); //$NON-NLS-1$ descBuffer.append(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.23") //$NON-NLS-1$ + DATE_FORMATTER.format(zustandBean.getDate())); reach.setDescription(descBuffer.toString()); // add reachSegments + profiles (.str) // we ignore the profileBeans and just add the segments, so we can even import projects // which are slightly inconsistent, maybe add warning messages later final ZustandSegmentBean[] segmentBeans = zustand.getSegmentBeans(); final WspWinProject wspwinProject = wspCfg.getProject(); final File profDir = wspwinProject.getProfDir(); // create reachSegments and associated profiles for (final ZustandSegmentBean bean : segmentBeans) { try { final ProfileBean fromBean = new ProfileBean(waterName, name, bean.getStationFrom(), bean.getFileNameFrom()); final IProfileFeature fromProf = importProfile(profDir, tuhhProject, importedProfiles, fromBean, isDirectionUpstreams, false); reach.createProfileSegment(fromProf, bean.getStationFrom().doubleValue()); if (bean == segmentBeans[segmentBeans.length - 1]) { // also add last profile final ProfileBean toBean = new ProfileBean(waterName, name, bean.getStationTo(), bean.getFileNameTo()); final IProfileFeature toProf = importProfile(profDir, tuhhProject, importedProfiles, toBean, isDirectionUpstreams, false); reach.createProfileSegment(toProf, bean.getStationTo().doubleValue()); } } catch (final CoreException e) { log.add(e.getStatus()); } catch (final Exception e) { log.add(IStatus.ERROR, e.getLocalizedMessage(), e); } } final WspmWaterBody waterBody = reach.getWaterBody(); // base name for runOffEvents and calculations. Needed, because in WspWin the runOffs and calculations belonged // always to a zustand. final String baseName = waterBody.getName() + "-" + zustandBean.getName() + " - "; //$NON-NLS-1$ //$NON-NLS-2$ // ////////////////////////////////////////////////////// // // add runoff events and waterlevel fixations(.wsf, .qwt) // // ////////////////////////////////////////////////////// // // map is used to remember position of runoff: used later by calculation to find reference final Map<Integer, String> runOffEventsByCount = new HashMap<>(); final Map<String, String> runOffEventsByName = new HashMap<>(); try { final RunOffEventBean[] runOffEventBeans = zustand.getRunOffEvents(); int count = 0; for (final RunOffEventBean bean : runOffEventBeans) { final IFeatureBindingCollection<IRunOffEvent> runoffEvents = waterBody.getRunoffEvents(); final IRunOffEvent newEvent = runoffEvents.addNew(IRunOffEvent.FEATURE_RUNOFF_EVENT); final String runoffEventName = baseName + bean.getName(); writeRunOffBeanIntoFeature(bean, runoffEventName, newEvent); // remember for reference from calculation runOffEventsByCount.put(count++, newEvent.getId()); runOffEventsByName.put(runoffEventName, newEvent.getId()); } } catch (final Exception e) { log.add(IStatus.ERROR, e.getLocalizedMessage(), e); } try { final RunOffEventBean[] wspFixesBeans = zustand.getWspFixations(); for (final RunOffEventBean bean : wspFixesBeans) { if (!bean.getEntries().isEmpty()) { final IFeatureBindingCollection<WspmFixation> fixations = waterBody.getWspFixations(); final WspmFixation wspFixation = fixations.addNew(WspmFixation.QNAME_FEATURE_WSPM_FIXATION); writeRunOffBeanIntoFeature(bean, baseName + bean.getName(), wspFixation); } } } catch (final Exception e) { log.add(IStatus.ERROR, e.getLocalizedMessage(), e); } // /////////////////////////////////////////// // // add einzelverluste / Verlustbeiwerte (.psi) // // /////////////////////////////////////////// // // map is used to remember station of local energy loss (Einzelverlust/Verlustbeiwert) final Map<BigDecimal, Integer> readLocEnergyLosses = new HashMap<>(); try { final LocalEnergyLossBean[] locEnergyLossBeans = zustand.getLosses(); int count = 0; for (final LocalEnergyLossBean bean : locEnergyLossBeans) { // remember station for reference readLocEnergyLosses.put(bean.getStation(), count++); } } catch (final Exception e) { log.add(IStatus.ERROR, e.getLocalizedMessage(), e); } for (final LocalEnergyLossBean energyLossBean : zustand.getLosses()) { final IProfileFeature profileFeature = reach.findProfile(energyLossBean.getStation()); final EnergylossProfileObject energyLoss = new EnergylossProfileObject(); final Pair<String, BigDecimal>[] entries = energyLossBean.getEntries(); for (final Pair<String, BigDecimal> entry : entries) { final Energyloss newEnergyloss = new Energyloss(entry.getLeft(), StringUtils.EMPTY, entry.getRight()); energyLoss.addEnergyloss(newEnergyloss); } ((ProfileFeatureBinding) profileFeature).getProfile().addProfileObjects(energyLoss); } // ///////////////////////////// // // add calculations (.ber, .001) // // ///////////////////////////// // try { final TYPE type = wspCfg.getType(); importCalculations(zustand, log, reach, wspwinProject, baseName, runOffEventsByCount, runOffEventsByName, type, targetContainer); } catch (final Exception e) { log.add(IStatus.ERROR, e.getLocalizedMessage(), e); } return log.asMultiStatus(message); } private static void importCalculations(final WspWinZustand zustand, final IStatusCollector log, final TuhhReach reach, final WspWinProject wspwinProject, final String baseName, final Map<Integer, String> readRunOffEventsByCount, final Map<String, String> runOffEventsByName, final TYPE projectType, final IContainer targetContainer) { final ICalculationWspmConverter converter = createCalculationConverter(projectType, reach, baseName, readRunOffEventsByCount, runOffEventsByName); final File dathDir = wspwinProject.getDathDir(); final File profDir = wspwinProject.getProfDir(); final CalculationResultConverter resultConverter = new CalculationResultConverter(projectType, baseName, log, targetContainer); final ICalculationContentBean[] calculations = zustand.getCalculations(); for (final ICalculationContentBean calculation : calculations) { try { converter.convert(calculation, profDir); final CalculationBean calculationBean = calculation.getCalculationBean(); resultConverter.convert(calculationBean, dathDir); } catch (final Exception e) { log.add(IStatus.ERROR, e.getLocalizedMessage(), e); } } } protected static ICalculationWspmConverter createCalculationConverter(final TYPE projectType, final TuhhReach reach, final String baseName, final Map<Integer, String> readRunOffEventsByCount, final Map<String, String> runOffEventsByName) { switch (projectType) { case PASCHE: return new CalculationPasche2WspmConverter(reach, baseName, readRunOffEventsByCount); case KNAUF: return new CalculationKnauf2WspmConverter(reach, baseName, runOffEventsByName); default: throw new IllegalArgumentException(); } } private static void writeRunOffBeanIntoFeature(final RunOffEventBean bean, final String name, final IObservationFeature observationFeature) { final IObservation<TupleResult> obs = observationFeature.toObservation(); obs.setName(name); obs.setDescription(Messages.getString("org.kalypso.model.wspm.tuhh.core.wspwin.WspWinImporter.28")); //$NON-NLS-1$ final TupleResult result = obs.getResult(); final int stationIndex = result.indexOfComponent(IRunOffEvent.COMPONENT_STATION); final int runoffIndex = result.indexOfComponent(IRunOffEvent.COMPONENT_RUNOFF); final int wspIndex = result.indexOfComponent(WspmFixation.COMPONENT_WSP); final int valueIndex = runoffIndex == -1 ? wspIndex : runoffIndex; final Map<BigDecimal, BigDecimal> values = bean.getEntries(); for (final Map.Entry<BigDecimal, BigDecimal> entry : values.entrySet()) { final IRecord record = result.createRecord(); result.add(record); record.setValue(stationIndex, entry.getKey()); record.setValue(valueIndex, entry.getValue()); } // TODO: WSP Fixierung nur schreiben, wenn Anzahl grer 0 observationFeature.saveObservation(obs); } /** Returns the content of the prof/probez.txt file */ private static String readProjectDescription(final WspWinProject wspWinProject) throws IOException { final File probezFile = wspWinProject.getProbezFile(); return FileUtils.readFileToString(probezFile, (Charset) null); } }