Java tutorial
/* * polymap.org * Copyright (C) 2014-2016, Falko Brutigam. All rights reserved. * * This 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 3.0 of * the License, or (at your option) any later version. * * This software 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. */ package org.polymap.wbv.mdb; import static org.polymap.wbv.model.fulltext.WaldbesitzerFulltextTransformer.whitespace; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.Set; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.google.common.base.Joiner; import com.healthmarketscience.jackcess.Database; import com.healthmarketscience.jackcess.DatabaseBuilder; import com.healthmarketscience.jackcess.Row; import com.healthmarketscience.jackcess.Table; import com.healthmarketscience.jackcess.util.LinkResolver; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.commands.operations.AbstractOperation; import org.eclipse.core.commands.operations.IUndoableOperation; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.rap.rwt.client.ClientFile; import org.polymap.core.runtime.SubMonitor; import org.polymap.model2.runtime.UnitOfWork; import org.polymap.wbv.model.Flurstueck; import org.polymap.wbv.model.Gemarkung; import org.polymap.wbv.model.Kontakt; import org.polymap.wbv.model.Revier; import org.polymap.wbv.model.Waldbesitzer; import org.polymap.wbv.model.Waldbesitzer.Waldeigentumsart; /** * Importiert Daten aus WVK_dat_<Reviername>.mdb * * @author <a href="http://www.polymap.de">Falko Brutigam</a> */ public class WvkImporter extends AbstractOperation implements IUndoableOperation { private static Log log = LogFactory.getLog(WvkImporter.class); public static final File BASEDIR = new File("."); // lokales Dir beim Start (workspace) private UnitOfWork uow; private InputStream in; private ClientFile clientFile; private String revier; private Map<String, String> gmks = new HashMap(); private Map<String, String> gmds = new HashMap(); private int wbImportCount = 0; private int flstImportCount = 0; private int adrImportCount = 0; private Map<String, Row> wbRows = new HashMap(5000); /** Die tatschlich importierten {@link Waldbesitzer#id()}s. */ private Set<String> wbIds = new HashSet(5000); public WvkImporter(UnitOfWork uow, ClientFile clientFile, InputStream in) { super("WVK-Daten importieren"); this.uow = uow; this.in = in; this.clientFile = clientFile; this.revier = StringUtils.substringAfterLast(FilenameUtils.getBaseName(clientFile.getName()), "_"); if (!Revier.all.get().containsKey(revier)) { throw new IllegalStateException("Das Revier gibt es nicht: " + revier); } } @Override public IStatus execute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { try { importData(monitor); return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS; } catch (Exception e) { throw new ExecutionException(e.getMessage(), e); } } public void importData(IProgressMonitor monitor) throws Exception { // upload -> temp file monitor.beginTask(getLabel(), 12); monitor.subTask("Upload"); File f = File.createTempFile("WVK_dat_", ".mdb"); try (FileOutputStream out = new FileOutputStream(f)) { IOUtils.copy(in, out); } monitor.worked(1); // monitor.subTask("Datenbank ffnen"); try (Database db = DatabaseBuilder.open(f)) { db.setLinkResolver(new LinkResolver() { @Override public Database resolveLinkedDatabase(Database linkerDb, String linkeeFileName) throws IOException { return DatabaseBuilder.open(new File(FilenameUtils.getName(linkeeFileName))); } }); monitor.worked(1); // Gemarkung: id -> name monitor.subTask("Gemarkungsnamen lesen"); Table table = db.getTable("ESt_Gemarkung"); for (Row row = table.getNextRow(); row != null && !monitor.isCanceled(); row = table.getNextRow()) { String id = String.valueOf(row.get("ID_Gemarkung")); gmks.put(id, (String) row.get("Gemarkung_Name")); } monitor.worked(1); log.info(revier + ": " + gmks.size() + " Gemarkungsschlssel gelesen."); // Gemeinden: id -> name monitor.subTask("Gemeindenamen lesen"); table = db.getTable("ESt_Gemeinde"); for (Row row = table.getNextRow(); row != null && !monitor.isCanceled(); row = table.getNextRow()) { String id = String.valueOf(row.get("ID_Gemeinde")); gmds.put(id, (String) row.get("Gemeinde_Name")); } monitor.worked(1); log.info(revier + ": " + gmds.size() + " Gemeindeschlssel gelesen."); // wbRows monitor.subTask("Waldbesitzer lesen"); table = db.getTable(new MdbEntityImporter(uow, Waldbesitzer.class).getTableName()); for (Row row = table.getNextRow(); row != null && !monitor.isCanceled(); row = table.getNextRow()) { wbRows.put(wbId(row, true), row); } monitor.worked(1); log.info(revier + ": " + wbRows.size() + " Waldbesitzer-Rows gelesen."); // Flurstuecke -> Waldbesitzer SubMonitor submon = new SubMonitor(monitor, 4); importFlurstuecke(db, submon); // Adressen fr importierte Waldbesitzer new MdbEntityImporter<Kontakt>(uow, Kontakt.class) { @Override public Kontakt createEntity(final Map row, String id) { Waldbesitzer wb = uow.entity(Waldbesitzer.class, wbId(row, true)); if (wb != null && wbIds.contains(wb.id())/*wb.status().equals( EntityStatus.CREATED )*/) { return wb.kontakte.createElement((Kontakt proto) -> { adrImportCount++; return fill(proto, row); }); } return null; } }.importTable(db, submon); log.info(revier + ": Kontakte: " + adrImportCount); monitor.done(); } } protected String wbId(Map<String, Object> row, boolean excOnFail) { Object id = row.get("ID_WBS"); if (id == null && excOnFail) { throw new IllegalStateException("Row has no ID_WBS: " + row); } else if (id == null) { log.info("Row has no ID_WBS: " + row); return null; } else { return Joiner.on(".").join("Waldbesitzer", revier, id.toString()); } } protected void importFlurstuecke(Database db, IProgressMonitor monitor) throws IOException { GmkImporter gmkHelper = new GmkImporter(); new MdbEntityImporter<Flurstueck>(uow, Flurstueck.class) { @Override public Flurstueck createEntity(final Map row, String id) { // Gemarkung finden String gemeindeId = String.valueOf(row.get("FL_Gemeinde")); String gemarkungId = String.valueOf(row.get("FL_Gemarkung")); String gmkschl = gmkHelper.gmkschl(gemeindeId, gemarkungId); Gemarkung gmk = gmkschl != null ? uow.entity(Gemarkung.class, gmkschl) : null; // Revier prfen if (gmk != null && !gmk.revier.get().equals(revier)) { return null; } // Flurstck trotzdem anlegen if (gmk == null) { log.warn("Keine Gemarkung fr: " + gemeindeId + " / " + gemarkungId); } // Waldbesitzer Row wbRow = wbRows.get(wbId(row, false)); if (wbRow == null) { log.warn("Flurstck ohne ID_WBS: " + row); return null; } Waldbesitzer wb = importWaldbesitzer(wbId(row, true), wbRow); // ohne Gmk gibt es keine Revierzuordnung und wir knnten ein Flst // mehrfach importieren Integer wkvId = (Integer) row.get("ID_FL"); if (wb.flurstuecke.stream().filter(fst -> Objects.equals(fst.wvkId.get(), wkvId)).findAny() .isPresent()) { log.warn("Flurstck ohne Gmk bereits importiert: " + row); return null; } return wb.flurstuecke.createElement((Flurstueck proto) -> { fill(proto, row); // if ("Waldfeststellung von Stefan Naumann 2009: 1,05ha".equals( proto.bemerkung.get() )) { // log.info( "row: " + row ); // log.info( "" + proto ); // log.info( "wbId: " + wbId( row, true ) ); // } proto.gemarkung.set(gmk); proto.zaehlerNenner.set(whitespace.matcher(proto.zaehlerNenner.get()).replaceAll("")); flstImportCount++; return proto; }); } }.importTable(db, monitor); log.info(revier + ": Waldbesitzer: " + wbImportCount + ", Flurstcke: " + flstImportCount); } protected Waldbesitzer importWaldbesitzer( String id, Row row ) { // if (id.equals( "Waldbesitzer.77719" )) { // log.info( "row: " + row ); // } Waldbesitzer wb = uow.entity( Waldbesitzer.class, id ); if (wb == null) { // create new wb = uow.createEntity( Waldbesitzer.class, id, (Waldbesitzer proto) -> { MdbEntityImporter<Waldbesitzer> wbImporter = new MdbEntityImporter( uow, Waldbesitzer.class ); wbImporter.fill( proto, row ); String ea = (String)row.get( "WBS_EA" ); switch (ea != null ? ea : "null") { case "P": proto.eigentumsArt.set( Waldeigentumsart.Privat ); break; case "K42": proto.eigentumsArt.set( Waldeigentumsart.Kirche42 ); break; case "K43": proto.eigentumsArt.set( Waldeigentumsart.Kirche43 ); break; case "C": proto.eigentumsArt.set( Waldeigentumsart.Krperschaft_Kommune ); break; case "T": proto.eigentumsArt.set( Waldeigentumsart.BVVG ); break; case "B": proto.eigentumsArt.set( Waldeigentumsart.Staat_Bund ); break; case "A": proto.eigentumsArt.set( Waldeigentumsart.Krperschaft_ZVB ); break; case "L": proto.eigentumsArt.set( Waldeigentumsart.Staat_Sachsen ); break; default : { log.warn( "Unbekannte Eigentumsart: " + ea ); proto.eigentumsArt.set( Waldeigentumsart.Unbekannt ); break; } } wbImportCount++; return proto; }); if (!wbIds.add( (String)wb.id() )) { throw new RuntimeException( "" ); } } else { // XXX check existing } return wb; } @Override public IStatus redo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { throw new RuntimeException("not yet implemented."); } @Override public IStatus undo(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { throw new RuntimeException("not yet implemented."); } }