org.polymap.alkis.model.AlkisRepository.java Source code

Java tutorial

Introduction

Here is the source code for org.polymap.alkis.model.AlkisRepository.java

Source

/* 
 * polymap.org
 * Copyright (C) 2015 Polymap GmbH. 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.alkis.model;

import static java.util.stream.Collectors.toMap;
import static org.apache.commons.lang3.StringUtils.substringAfterLast;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;

import org.geotools.data.DataStore;
import org.geotools.data.postgis.PostgisNGDataStoreFactory;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.jdbc.AutoGeneratedPrimaryKeyColumn;
import org.geotools.jdbc.JDBCDataStore;
import org.geotools.jdbc.JDBCDataStoreFactory;
import org.geotools.jdbc.PrimaryKey;
import org.geotools.jdbc.PrimaryKeyFinder;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.identity.Identifier;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.search.BooleanQuery;

import org.polymap.core.runtime.Lazy;
import org.polymap.core.runtime.LockedLazyInit;
import org.polymap.core.runtime.PlainLazyInit;

import org.polymap.rhei.fulltext.FullQueryProposalDecorator;
import org.polymap.rhei.fulltext.FulltextIndex;
import org.polymap.rhei.fulltext.indexing.LowerCaseTokenFilter;
import org.polymap.rhei.fulltext.store.lucene.LuceneFulltextIndex;

import org.polymap.alkis.model.fulltext.FlurstueckTransformer;
import org.polymap.alkis.model.fulltext.FlurstueckUpdater;
import org.polymap.alkis.model.fulltext.ZaehlerNennerQueryDecorator;
import org.polymap.model2.Composite;
import org.polymap.model2.query.Query;
import org.polymap.model2.query.ResultSet;
import org.polymap.model2.runtime.CompositeInfo;
import org.polymap.model2.runtime.EntityRepository;
import org.polymap.model2.runtime.UnitOfWork;
import org.polymap.model2.store.geotools.FeatureStoreAdapter;
import org.polymap.model2.store.geotools.FilterWrapper;

/**
 * 
 *
 * @author <a href="http://www.polymap.de">Falko Brutigam</a>
 */
public class AlkisRepository {

    private static Log log = LogFactory.getLog(AlkisRepository.class);

    public static final String DB_NAME = "ALKIS";

    public static final FilterFactory ff = CommonFactoryFinder.getFilterFactory(null);

    /** Maximale Gre der Ergebnismenge fr Volltextsuche und Anzeige in Tabelle. */
    public static final int MAX_RESULTS = Integer
            .parseInt(System.getProperty("org.polymap.alkis.maxResults", "1000"));

    /** */
    public static final String DATA_DIR = System.getProperty("org.polymap.alkis.dataDir",
            "/home/falko/servers/workspace-alkis/data/org.polymap.alkis");

    /**
     * Initialize global things.
     */
    public static void init() {
        instance.get();
    }

    /**
     * The global instance, lazily initialized.
     */
    public static final Supplier<AlkisRepository> instance = new LockedLazyInit(() -> new AlkisRepository());

    // instance *******************************************

    private EntityRepository repo;

    private LuceneFulltextIndex fulltextIndex;

    private DataStore ds;

    public Lazy<Map<String, AX_LagebezeichnungKatalog>> lageKatalog = new PlainLazyInit(() -> {
        return newUnitOfWork().query(AX_LagebezeichnungKatalog.class).execute().stream()
                .collect(toMap(e -> e.lage.get(), e -> e, (e1, e2) -> e1));
    });

    public Lazy<Map<String, AX_Buchungsblattbezirk>> bbbezirk = new PlainLazyInit(() -> {
        return newUnitOfWork().query(AX_Buchungsblattbezirk.class).execute().stream()
                .collect(toMap(e -> e.bezirknummer.get(), e -> e, (e1, e2) -> e1));
    });

    /**
     * Configure and initializing the one and only global instance.
     */
    private AlkisRepository() {
        try {
            log.info("Assembling repository...");

            //            Logging.GEOTOOLS.setLoggerFactory( "org.geotools.util.logging.CommonsLoggerFactory" );

            //
            BooleanQuery.setMaxClauseCount(MAX_RESULTS * 2);
            log.info("Maximale Anzahl Lucene-Klauseln erhht auf: " + BooleanQuery.getMaxClauseCount());

            // init fulltext
            File dataDir = new File(DATA_DIR);
            fulltextIndex = new LuceneFulltextIndex(new File(dataDir, "fulltext"));
            fulltextIndex.addTokenFilter(new LowerCaseTokenFilter());

            // store
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("dbtype", "postgis");
            params.put("host", "localhost");
            params.put("port", 5432);
            params.put("schema", "public");
            params.put("database", "ALKIS");
            params.put("user", "postgres");
            params.put("passwd", "postgres");
            params.put(JDBCDataStoreFactory.MAXCONN.key, 24);
            params.put(JDBCDataStoreFactory.MAXWAIT.key, 20);
            ds = new PostgisNGDataStoreFactory().createDataStore(params);

            // primary key: gml_id
            ((JDBCDataStore) ds).setPrimaryKeyFinder(new PrimaryKeyFinder() {
                @Override
                public PrimaryKey getPrimaryKey(JDBCDataStore store, String schema, String table, Connection cx)
                        throws SQLException {
                    // Alkis_Beziehungen
                    if (table.equals(Alkis_Beziehungen.TYPE.info().getNameInStore())) {
                        AutoGeneratedPrimaryKeyColumn col = new AutoGeneratedPrimaryKeyColumn("ogc_fid",
                                String.class);
                        return new PrimaryKey(table, Collections.singletonList(col));
                    }
                    // AX_*
                    else {
                        AutoGeneratedPrimaryKeyColumn col = new AutoGeneratedPrimaryKeyColumn("gml_id",
                                String.class);
                        return new PrimaryKey(table, Collections.singletonList(col));
                    }
                }
            });

            FeatureStoreAdapter store = new FeatureStoreAdapter(ds).createOrUpdateSchemas.put(false);

            // repo
            repo = EntityRepository.newConfiguration().entities.set(new Class[] { AX_Flurstueck.class,
                    AX_Buchungsstelle.class, AX_Buchungsblatt.class, AX_Buchungsblattbezirk.class, AX_Person.class,
                    AX_Anschrift.class, AX_LagebezeichnungMitHausnummer.class,
                    AX_LagebezeichnungOhneHausnummer.class, AX_LagebezeichnungKatalog.class, AX_Namensnummer.class,
                    AX_Gemarkung.class, AX_Gemeinde.class, Alkis_Beziehungen.class }).store.set(
                            //new FulltextIndexer( fulltextIndex, new TypeFilter( Waldbesitzer.class ), newArrayList( wbTransformer ),
                            store) //)
                            .create();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public EntityRepository repo() {
        return repo;
    }

    public FulltextIndex fulltextIndex() {
        FulltextIndex result = new LowerCaseTokenFilter(fulltextIndex);
        // groe Datenbank mit vielen Wrtern: mehr Chancen etwas zu finden
        result = new FullQueryProposalDecorator(result).proposalIncreaseFactor.put(10);
        result = new ZaehlerNennerQueryDecorator(result);
        return result;
    }

    public void updateFulltext(int max) throws Exception {
        log.info("Checking fulltext index...");
        if (fulltextIndex.isEmpty()) {
            log.info("    Starting update...");
            new FlurstueckUpdater(AlkisRepository.instance.get(), fulltextIndex).max.put(max).run();
        }
    }

    public Query<AX_Flurstueck> fulltextQuery(String query, int maxResults, UnitOfWork uow) throws Exception {
        Set<Identifier> ids = new HashSet(1024);
        fulltextIndex().search(query, maxResults).forEach(record -> {
            String id = substringAfterLast(record.getString(FulltextIndex.FIELD_ID), ".");
            if (id.length() > 0) {
                ids.add(ff.featureId(id));
            } else {
                log.warn("No FIELD_ID in record: " + record);
            }
        });
        log.info("Filter:" + ff.id(ids));
        return uow.query(AX_Flurstueck.class).where(new FilterWrapper(ff.id(ids)));
    }

    public <T extends Composite> CompositeInfo<T> infoOf(Class<T> compositeClass) {
        return repo.infoOf(compositeClass);
    }

    public UnitOfWork newUnitOfWork() {
        return repo.newUnitOfWork();
    }

    /**
     * Simple access test.
     */
    public static void main(String[] args) throws Exception {
        AlkisRepository r = new AlkisRepository();

        // type names
        String[] typeNames = r.ds.getTypeNames();
        println("TypeNames:", Arrays.asList(typeNames));

        println("\n", AX_Flurstueck.class.getSimpleName(), " =============================================");
        println(r.ds.getSchema(AX_Flurstueck.TYPE.info().getNameInStore()));

        //
        UnitOfWork uow = r.newUnitOfWork();

        //        // Gemarkungen prfen
        //        Map<String,AX_Gemarkung> gems = new HashMap();
        //        uow.query( AX_Gemarkung.class ).execute().stream().forEach( g -> {
        //            println( "Gemarkung: " + g.gemarkungsnummer.get() + " - " + g.bezeichnung.get() );
        //            if (gems.put( g.gemarkungsnummer.get(), g ) != null) {
        //                println( "   !!!" );
        //            }
        //        });

        ResultSet<AX_Flurstueck> rs = uow.query(AX_Flurstueck.class)
                //.where( new FilterWrapper( ff.) )
                .maxResults(20).execute();
        for (AX_Flurstueck fst : rs) {
            //EntityHierachyPrinter.on( fst, (entity,assocname,assocType) -> true ).run();

            //            fst.lagebezeichnung.get().forEach( lbz -> 
            //                    EntityHierachyPrinter.on( lbz, (entity,assocname,assocType) -> true ).run() );
            //    
            //            fst.lagebezeichnungOhne.get().forEach( lbz -> 
            //                    EntityHierachyPrinter.on( lbz, (entity,assocname,assocType) -> true ).run() );

            println("JSON:" + new FlurstueckTransformer().apply(fst).toString(4));

            //            println( "Blattart: " + fst.buchungsstelle.get().buchungsblatt.get().blattart.get() );
            //            println( "Gemarkung: " + fst.gemarkung().bezeichnung.get() );
            //            println( "Gemeinde: " + fst.gemeinde().bezeichnung.get() );

            println("gem: " + fst.gemeinde.get() + "/" + fst.gemarkungsnummer.get());
        }

        //        // id queryString
        //        AX_Flurstueck fst = uow.entity( AX_Flurstueck.class, "DESTLIKA0002XWdg" );
        //        println( "-> " + fst.lagebezeichnung.get() );

        //        println( "\n", AX_LagebezeichnungMitHausnummer.class.getSimpleName(), " =============================================" );
        //        uow.query( AX_LagebezeichnungMitHausnummer.class ).maxResults( 1000 ).execute().stream().forEach( lbz -> {
        //            lbz.katalogeintrag().ifPresent( e -> println( "Lage-Katalog: " + e.bezeichnung.get() ) );
        //        });

        //      println( "\n", AX_Person.class.getSimpleName(), " =============================================" );
        //      uow.query( AX_Person.class ).maxResults( 1 ).execute().stream().forEach( person -> {
        //          EntityHierachyPrinter.on( person, (entity,assocname,assocType) -> {
        //              return true;
        //          }).run();
        //      });

        //        println( "\nAX_Namensnummer =============================================" );
        //        uow.query( AX_Namensnummer.class ).maxResults( 1 ).execute().stream().forEach( nn -> {
        //            EntityHierachyPrinter.on( nn, (entity,assocname,assocType) -> {
        //                return true;
        //            }).run();
        //        });

        //        println( "\nAX_Buchungsstelle ===========================================" );
        //        uow.query( AX_Buchungsstelle.class ).maxResults( 1 ).execute().stream().forEach( bs -> {
        //            EntityHierachyPrinter.on( bs, (entity,assocname,assocType) -> {
        //                return true;
        //            }).run();
        //        });

        //        println( "\nAX_Buchungsblatt ===========================================" );
        //        uow.query( AX_Buchungsblatt.class ).maxResults( 10 ).execute().stream().forEach( bb -> {
        //            EntityHierachyPrinter.on( bb, (entity,assocname,assocType) -> {
        //                return true;
        //            }).run();
        //        });

        //      AX_Namensnummer nn = uow.entity( AX_Namensnummer.class, "DESTLIKA00028H3S" );
        //      EntityHierachyPrinter.on( nn, (entity,assocname,assocType) -> {
        //          return true;
        //      }).run();

    }

    protected static void println(Object... parts) {
        print(parts);
        System.out.println("");
    }

    protected static void print(Object... parts) {
        Arrays.asList(parts).stream().forEach(part -> {
            System.out.print(part != null ? part.toString() : "[null]");
        });
    }

}