Search in sources :

Example 1 with TreeElementMapper

use of org.geotoolkit.index.tree.TreeElementMapper in project geotoolkit by Geomatys.

the class SQLRtreeManager method get.

public static synchronized Tree<NamedEnvelope> get(final Path directory, final Object owner) {
    Tree<NamedEnvelope> tree = CACHED_TREES.get(directory);
    if (tree == null || tree.isClosed()) {
        if (existTree(directory)) {
            TreeElementMapper treeMapper = null;
            try {
                if (PGDataSource.isSetPGDataSource()) {
                    if (PGDataSource.isPostgres) {
                        DataSource ds = PGDataSource.getDataSource();
                        treeMapper = new LucenePostgresSQLTreeEltMapper(DEFAULT_CRS, ds, directory);
                        byte[] data = TreeAccessSQLByteArray.getData(directory, ds);
                        tree = new PGTreeWrapper(data, directory, ds, treeMapper);
                    } else {
                        DataSource ds = PGDataSource.getDataSource();
                        treeMapper = new LuceneHSQLTreeEltMapper(DEFAULT_CRS, ds, directory);
                        byte[] data = TreeAccessSQLByteArray.getData(directory, ds);
                        tree = new PGTreeWrapper(data, directory, ds, treeMapper);
                    }
                } else {
                    // derby DB as default
                    final Path treeFile = directory.resolve("tree.bin");
                    DataSource ds = LuceneDerbySQLTreeEltMapper.getDataSource(directory);
                    treeMapper = new LuceneDerbySQLTreeEltMapper(DEFAULT_CRS, ds);
                    tree = new FileStarRTree<>(treeFile.toFile().toPath(), treeMapper);
                }
            } catch (Exception e) {
                if (treeMapper != null) {
                    try {
                        treeMapper.close();
                    } catch (Exception bis) {
                        e.addSuppressed(bis);
                    }
                }
                LOGGER.log(Level.SEVERE, "Cannot re-open RTRee", e);
                return null;
            }
        } else {
            tree = buildNewTree(directory);
        }
        final List<Object> owners = new ArrayList<>();
        owners.add(owner);
        TREE_OWNERS.put(directory, owners);
        CACHED_TREES.put(directory, tree);
    } else {
        // look if the owner is already registered
        final List<Object> owners = TREE_OWNERS.get(directory);
        if (!owners.contains(owner)) {
            owners.add(owner);
        }
    }
    return tree;
}
Also used : PGTreeWrapper(org.geotoolkit.index.tree.manager.postgres.PGTreeWrapper) Path(java.nio.file.Path) ArrayList(java.util.ArrayList) LucenePostgresSQLTreeEltMapper(org.geotoolkit.index.tree.manager.postgres.LucenePostgresSQLTreeEltMapper) IOException(java.io.IOException) SQLException(java.sql.SQLException) StoreIndexException(org.geotoolkit.index.tree.StoreIndexException) PGDataSource(org.geotoolkit.index.tree.manager.postgres.PGDataSource) DataSource(javax.sql.DataSource) TreeElementMapper(org.geotoolkit.index.tree.TreeElementMapper) LuceneHSQLTreeEltMapper(org.geotoolkit.index.tree.manager.postgres.LuceneHSQLTreeEltMapper)

Example 2 with TreeElementMapper

use of org.geotoolkit.index.tree.TreeElementMapper in project geotoolkit by Geomatys.

the class LuceneOGCWeight method scorer.

@Override
public Scorer scorer(LeafReaderContext context) throws IOException {
    // final SortedDocValues values = context.reader().getSortedDocValues(IDENTIFIER_FIELD_NAME);
    final LeafReader reader = context.reader();
    boolean treeSearch = false;
    boolean reverse = false;
    boolean distanceFilter = false;
    final Set<String> treeMatching = new HashSet<>();
    if (tree != null) {
        /*
             * For distance buffer filter no envelope only mode
             */
        List<Expression<Object, ?>> expressions = filter.getExpressions();
        Expression e2 = (expressions.size() >= 2) ? expressions.get(1) : null;
        if (filter instanceof DistanceOperator) {
            distanceFilter = true;
            reverse = filter.getOperatorType() == DistanceOperatorName.BEYOND;
            final DistanceOperator sp = (DistanceOperator) filter;
            if (e2 instanceof Literal) {
                try {
                    final Literal lit = (Literal) e2;
                    Quantity distance = sp.getDistance();
                    final GeneralEnvelope bound = getExtendedReprojectedEnvelope(lit.getValue(), tree.getCrs(), distance.getUnit().toString(), distance.getValue().doubleValue());
                    final int[] resultID = tree.searchID(bound);
                    Arrays.sort(resultID);
                    treeMatching.clear();
                    TreeElementMapper<NamedEnvelope> tem = tree.getTreeElementMapper();
                    for (int id : resultID) {
                        final NamedEnvelope env = tem.getObjectFromTreeIdentifier(id);
                        if (env != null) {
                            treeMatching.add(env.getId());
                        }
                    }
                    treeSearch = true;
                } catch (FactoryException ex) {
                    throw new IOException(ex);
                } catch (StoreIndexException ex) {
                    Throwable cause = ex.getCause();
                    if (cause instanceof IOException) {
                        throw (IOException) cause;
                    } else {
                        throw new IOException(ex);
                    }
                }
            } else {
                LOGGER.log(Level.WARNING, "Not a literal for spatial filter:{0}", e2);
            }
        } else if (filter instanceof BinarySpatialOperator) {
            final BinarySpatialOperator sp = (BinarySpatialOperator) filter;
            if (e2 instanceof Literal) {
                final Literal lit = (Literal) e2;
                final Envelope boundFilter = getReprojectedEnvelope(lit.getValue(), tree.getCrs());
                try {
                    if (filterType == SpatialFilterType.CROSSES || !envelopeOnly) {
                        if (filterType == SpatialFilterType.DISJOINT) {
                            reverse = true;
                        }
                        final int[] resultID = tree.searchID(boundFilter);
                        Arrays.sort(resultID);
                        final TreeElementMapper<NamedEnvelope> tem = tree.getTreeElementMapper();
                        treeMatching.clear();
                        for (int id : resultID) {
                            final NamedEnvelope env = tem.getObjectFromTreeIdentifier(id);
                            if (env != null) {
                                treeMatching.add(env.getId());
                            }
                        }
                        treeSearch = true;
                        envelopeOnly = false;
                    } else {
                        final int[] resultID = TreeX.search(tree, boundFilter, filterType);
                        Arrays.sort(resultID);
                        final TreeElementMapper<NamedEnvelope> tem = tree.getTreeElementMapper();
                        treeMatching.clear();
                        for (int id : resultID) {
                            final NamedEnvelope env = tem.getObjectFromTreeIdentifier(id);
                            if (env != null) {
                                treeMatching.add(env.getId());
                            }
                        }
                        treeSearch = true;
                    }
                } catch (StoreIndexException ex) {
                    Throwable cause = ex.getCause();
                    if (cause instanceof IOException) {
                        throw (IOException) cause;
                    } else {
                        throw new IOException(ex);
                    }
                }
            } else {
                LOGGER.log(Level.WARNING, "Not a literal for spatial filter:{0}", e2);
            }
        } else {
            LOGGER.log(Level.WARNING, "not a spatial operator:{0}", filter.getClass().getName());
        }
    } else {
        LOGGER.finer("Null R-tree in spatial search");
    }
    final BitSet set = new FixedBitSet(reader.maxDoc());
    Bits b = reader.getLiveDocs();
    if (b == null) {
        b = new Bits.MatchAllBits(reader.maxDoc());
    }
    for (int i = 0; i < b.length(); i++) {
        if (b.get(i)) {
            final int docId = i;
            final Document doc = reader.document(docId, ID_FIELDS);
            final String id = doc.get(IDENTIFIER_FIELD_NAME);
            final boolean match = treeMatching.contains(id);
            if (treeSearch && reverse && !match) {
                set.set(docId);
            } else if (!treeSearch || match) {
                if (envelopeOnly && !distanceFilter) {
                    set.set(docId);
                } else {
                    final Document geoDoc = reader.document(docId, GEOMETRY_FIELDS);
                    if (filter.test(geoDoc)) {
                        set.set(docId);
                    }
                }
            }
        }
    }
    return new ConstantScoreScorer(this, boost, scoreMode, new BitSetIterator(set, 5));
}
Also used : NamedEnvelope(org.geotoolkit.index.tree.manager.NamedEnvelope) FactoryException(org.opengis.util.FactoryException) Envelope(org.opengis.geometry.Envelope) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) LuceneUtils.getReprojectedEnvelope(org.geotoolkit.lucene.LuceneUtils.getReprojectedEnvelope) LuceneUtils.getExtendedReprojectedEnvelope(org.geotoolkit.lucene.LuceneUtils.getExtendedReprojectedEnvelope) NamedEnvelope(org.geotoolkit.index.tree.manager.NamedEnvelope) Document(org.apache.lucene.document.Document) ConstantScoreScorer(org.apache.lucene.search.ConstantScoreScorer) FixedBitSet(org.apache.lucene.util.FixedBitSet) Literal(org.opengis.filter.Literal) HashSet(java.util.HashSet) BinarySpatialOperator(org.opengis.filter.BinarySpatialOperator) StoreIndexException(org.geotoolkit.index.tree.StoreIndexException) BitSetIterator(org.apache.lucene.util.BitSetIterator) LeafReader(org.apache.lucene.index.LeafReader) DistanceOperator(org.opengis.filter.DistanceOperator) FixedBitSet(org.apache.lucene.util.FixedBitSet) BitSet(org.apache.lucene.util.BitSet) Quantity(javax.measure.Quantity) IOException(java.io.IOException) Expression(org.opengis.filter.Expression) TreeElementMapper(org.geotoolkit.index.tree.TreeElementMapper) Bits(org.apache.lucene.util.Bits) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope)

Example 3 with TreeElementMapper

use of org.geotoolkit.index.tree.TreeElementMapper in project geotoolkit by Geomatys.

the class TreeDemo method main.

public static void main(String[] args) throws StoreIndexException, IOException, ClassNotFoundException {
    /*
         * In these examples we'll show how to build and create a RTree according to our use case.
         * 2 RTree storage are made, the first where RTree is stored in computer memory
         * and the second where RTree is stored in file on hard drive at a path stipulated by the user.
         *
         * RTree which is stored in computer memory :
         *      - advantages    : all RTree action are faster than the others because do not require hard drive access.
         *      - inconvenients : computer RAM memory limits data number which should be inserted.
         *
         * RTree which is stored on hard drive :
         *      - advantages    : there is no data number limit of insertions.
         *      - inconvenients : all RTree action are slower than the others because require hard drive access.
         */
    /*
         * First example RTree stored in our computer memory.
         * In this example user has to know he can't insert too many elements, to not overflow memory.
         * For this example we choose StarRTree.
         */
    /*
         * In each RTree we need another object called TreeElementMapper.
         * This Object allows to link Integer identifier stored in RTree and datas.
         * (It is an internal operation). User should just override some methods from TreeElementMapper.
         * TreeElementMapper uses Generic template and user may specify the type.
         * In the present example we are working with Envelope type object. Moreover to store Envelope object we use an Envelope table.
         * User can choose List or Map or other object according to his needs.
         */
    final TreeElementMapper<Envelope> demoMemoryTreeEltMapper = new TreeElementMapper<Envelope>() {

        private int currentSize = 100;

        private Envelope[] envelopes = new Envelope[currentSize];

        private boolean isClose = false;

        /**
         * {@inheritDoc }
         */
        @Override
        public int getTreeIdentifier(final Envelope object) throws IOException {
            int i = 0;
            for (Envelope env : envelopes) {
                if (env.equals(object))
                    return i + 1;
                i++;
            }
            throw new IllegalStateException("getTreeIdentifier : impossible to find tree identifier from Envelope object.");
        }

        /**
         * {@inheritDoc }
         */
        @Override
        public Envelope getEnvelope(final Envelope object) throws IOException {
            return object;
        }

        /**
         * {@inheritDoc }
         */
        @Override
        public void setTreeIdentifier(final Envelope object, final int treeIdentifier) throws IOException {
            final int envID = treeIdentifier - 1;
            if (envID >= currentSize) {
                currentSize = currentSize << 1;
                envelopes = Arrays.copyOf(envelopes, currentSize);
            }
            envelopes[envID] = object;
        }

        /**
         * {@inheritDoc }
         */
        @Override
        public Envelope getObjectFromTreeIdentifier(final int treeIdentifier) throws IOException {
            final int envID = treeIdentifier - 1;
            if (envID >= currentSize)
                throw new IllegalStateException("getObjectFromTreeIdentifier : impossible to find object from identifier.");
            return envelopes[envID];
        }

        /**
         * {@inheritDoc }
         */
        @Override
        public void clear() throws IOException {
            currentSize = 100;
            envelopes = new Envelope[currentSize];
        }

        /**
         * {@inheritDoc }
         */
        @Override
        public void close() throws IOException {
            // no stream to close.
            isClose = true;
        }

        /**
         * {@inheritDoc }
         */
        @Override
        public boolean isClosed() {
            return isClose;
        }

        @Override
        public void flush() throws IOException {
        // do nothing
        }

        @Override
        public Map<Integer, Envelope> getFullMap() throws IOException {
            return new HashMap<>();
        }
    };
    /*
         * After creating TreeElementMapper object we create RTree.
         */
    final Tree demoMemoryRTree = new MemoryStarRTree<Envelope>(5, DEMO_CRS, demoMemoryTreeEltMapper);
    /*
         * get datas.
         */
    Envelope[] insertedEnvelope = createData(20);
    /*
         * Now insert data in RTree.
         */
    for (Envelope data : insertedEnvelope) {
        demoMemoryRTree.insert(data);
    }
    System.out.println("Tree Demo : " + demoMemoryRTree.toString());
    /*
         * Now we should search.
         */
    final GeneralEnvelope envelopeSearch = new GeneralEnvelope(DEMO_CRS);
    envelopeSearch.setEnvelope(-45, -50, 110, 75);
    /*
         * There is two way to search.
         * First, we can get a table of data identifiers which matches with the search area.
         */
    int[] treeIdentifierResult = demoMemoryRTree.searchID(envelopeSearch);
    System.out.println("identifiers which match : " + Arrays.toString(treeIdentifierResult));
    /*
         * To obtain data you have to ask data from TreeElementMapper as below.
         */
    final Envelope[] resultData = new Envelope[treeIdentifierResult.length];
    for (int id = 0; id < treeIdentifierResult.length; id++) {
        resultData[id] = demoMemoryTreeEltMapper.getObjectFromTreeIdentifier(treeIdentifierResult[id]);
    }
    /*
         * Secondly, we can get an iterator which iterates on each treeIdentifier search result.
         */
    TreeIdentifierIterator treeIterator = demoMemoryRTree.search(envelopeSearch);
    /*
         * And we can get data object result as below.
         */
    List<Envelope> listDataResult = new ArrayList<Envelope>();
    while (treeIterator.hasNext()) {
        listDataResult.add(demoMemoryTreeEltMapper.getObjectFromTreeIdentifier(treeIterator.nextInt()));
    }
    /*
         * Moreover we can also remove some elements in index RTree.
         */
    int idEnv = 1;
    for (Envelope env : insertedEnvelope) {
        demoMemoryRTree.remove(env);
        if (idEnv % 5 == 0) {
            System.out.println("RTree : during remove action after " + idEnv + " elements : " + demoMemoryRTree.toString());
        }
        idEnv++;
    }
    /**
     ********************************
     */
    /*
         * Second example: RTree stored on user computer hard disk.
         * If the user doesn't know if there is enought memory on his computer or
         * if he knows that all the data overflow memory, he may choose to store RTree
         * on his computer hard drive.
         */
    /*
         * Build the 2 files to store RTree.
         * One to store RTree architecture.
         * The other to store TreeElementMapper architecture.
         */
    final File treeFile = File.createTempFile("tree", "bin");
    final File treeELTMapperFile = File.createTempFile("mapper", "bin");
    /*
         * First, like previously, we have to begin creating an appropriate
         * TreeElementMapper to link treeIdentifier and stored object.
         * In our case we would store elements on hard drive, then we would override
         * a TreeElementMapper implementation called FileTreeElementMapper.
         * See DemoFileTreeElementMapper class.
         */
    TreeElementMapper<Envelope> demoFileTreeEltMapper = new DemoFileTreeElementMapper(treeELTMapperFile, DEMO_CRS);
    /*
         * Be carefull it exists 2 ways to open a FileRTree.
         * If tree has never been built previously, the user should open RTree in writing action.(see Javadoc)
         * Unlike if a tree has already been saved on a filled file,
         * the user should open RTree in reading/writing and use constructor in accordance with it.
         */
    /*
         * First, we make an RTree as if it has never been created before.
         */
    Tree<Envelope> demoFileRTree = new FileStarRTree<Envelope>(treeFile.toPath(), 4, DEMO_CRS, demoFileTreeEltMapper);
    /*
         * At this step the RTree is empty and we can fill it like previously.
         */
    /*
         * get datas.
         */
    insertedEnvelope = createData(20);
    /*
         * Now insert data in RTree.
         */
    for (Envelope data : insertedEnvelope) {
        demoFileRTree.insert(data);
    }
    /*
         * At this step we can use search or remove action freely.
         * But if we want to save the RTree to re-open it later we MUST call close method
         * on RTree and TreeElementMapper to finish to write Tree informations.
         *
         * Be carefull not to open an RTree in reading if it has not been closed before.
         *
         * In this example we close RTree and TreeElementMapper to re-open it after.
         */
    demoFileRTree.close();
    demoFileTreeEltMapper.close();
    /*
         * Re-open RTree.
         */
    /*
         * First we open again TreeElementMapper.
         */
    demoFileTreeEltMapper = new DemoFileTreeElementMapper(treeELTMapperFile, DEMO_CRS);
    /*
         * Then RTree.
         */
    demoFileRTree = new FileStarRTree<Envelope>(treeFile.toPath(), demoFileTreeEltMapper);
    /*
         * At this step we can use search or remove action freely.
         * Moreover we can also add some data as below.
         */
    // five new datas.
    insertedEnvelope = createData(5);
    System.out.println("RTree : before re-inserting datas : " + demoFileRTree.toString());
    /*
         * Now insert data in RTree.
         */
    for (Envelope data : insertedEnvelope) {
        demoFileRTree.insert(data);
    }
    System.out.println("RTree : after re-inserting datas : " + demoFileRTree.toString());
    /*
         * Like previously if we want to save changes and re-open RTree afterwards we call close() methods.
         */
    demoFileRTree.close();
    demoFileTreeEltMapper.close();
}
Also used : TreeIdentifierIterator(org.geotoolkit.index.tree.TreeIdentifierIterator) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Envelope(org.opengis.geometry.Envelope) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) FileStarRTree(org.geotoolkit.index.tree.star.FileStarRTree) TreeElementMapper(org.geotoolkit.index.tree.TreeElementMapper) Tree(org.geotoolkit.index.tree.Tree) FileStarRTree(org.geotoolkit.index.tree.star.FileStarRTree) MemoryStarRTree(org.geotoolkit.index.tree.star.MemoryStarRTree) MemoryStarRTree(org.geotoolkit.index.tree.star.MemoryStarRTree) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) File(java.io.File)

Example 4 with TreeElementMapper

use of org.geotoolkit.index.tree.TreeElementMapper in project geotoolkit by Geomatys.

the class SQLRtreeManager method buildNewTree.

private static Tree buildNewTree(final Path directory) {
    if (Files.exists(directory)) {
        TreeElementMapper treeMapper = null;
        try {
            // creating tree (R-Tree)------------------------------------------------
            final Path treeFile = directory.resolve("tree.bin");
            Files.createFile(treeFile);
            // postgres
            if (PGDataSource.isSetPGDataSource()) {
                if (PGDataSource.isPostgres) {
                    treeMapper = LucenePostgresSQLTreeEltMapper.createTreeEltMapperWithDB(directory);
                    return new PGTreeWrapper(directory, PGDataSource.getDataSource(), treeMapper, DEFAULT_CRS);
                } else {
                    treeMapper = LuceneHSQLTreeEltMapper.createTreeEltMapperWithDB(directory);
                    return new PGTreeWrapper(directory, PGDataSource.getDataSource(), treeMapper, DEFAULT_CRS);
                }
            } else {
                treeMapper = LuceneDerbySQLTreeEltMapper.createTreeEltMapperWithDB(directory);
                return new FileStarRTree(treeFile.toFile().toPath(), 5, DEFAULT_CRS, treeMapper);
            }
        } catch (SQLException | IOException | StoreIndexException ex) {
            if (treeMapper != null) {
                try {
                    treeMapper.close();
                } catch (Exception bis) {
                    ex.addSuppressed(bis);
                }
            }
            LOGGER.log(Level.WARNING, "Unable to create RTree", ex);
        }
    }
    return null;
}
Also used : Path(java.nio.file.Path) PGTreeWrapper(org.geotoolkit.index.tree.manager.postgres.PGTreeWrapper) StoreIndexException(org.geotoolkit.index.tree.StoreIndexException) SQLException(java.sql.SQLException) TreeElementMapper(org.geotoolkit.index.tree.TreeElementMapper) IOException(java.io.IOException) FileStarRTree(org.geotoolkit.index.tree.star.FileStarRTree) IOException(java.io.IOException) SQLException(java.sql.SQLException) StoreIndexException(org.geotoolkit.index.tree.StoreIndexException)

Aggregations

TreeElementMapper (org.geotoolkit.index.tree.TreeElementMapper)4 IOException (java.io.IOException)3 StoreIndexException (org.geotoolkit.index.tree.StoreIndexException)3 Path (java.nio.file.Path)2 SQLException (java.sql.SQLException)2 ArrayList (java.util.ArrayList)2 GeneralEnvelope (org.apache.sis.geometry.GeneralEnvelope)2 PGTreeWrapper (org.geotoolkit.index.tree.manager.postgres.PGTreeWrapper)2 FileStarRTree (org.geotoolkit.index.tree.star.FileStarRTree)2 Envelope (org.opengis.geometry.Envelope)2 File (java.io.File)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Quantity (javax.measure.Quantity)1 DataSource (javax.sql.DataSource)1 Document (org.apache.lucene.document.Document)1 LeafReader (org.apache.lucene.index.LeafReader)1 ConstantScoreScorer (org.apache.lucene.search.ConstantScoreScorer)1 BitSet (org.apache.lucene.util.BitSet)1 BitSetIterator (org.apache.lucene.util.BitSetIterator)1