001/**
002 * Copyright (C) 2007 - 2016, Jens Lehmann
003 * <p>
004 * This file is part of DL-Learner.
005 * <p>
006 * DL-Learner is free software; you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation; either version 3 of the License, or
009 * (at your option) any later version.
010 * <p>
011 * DL-Learner is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014 * GNU General Public License for more details.
015 * <p>
016 * You should have received a copy of the GNU General Public License
017 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
018 */
019package org.dllearner.kb.sparql;
020
021import com.google.common.cache.CacheBuilder;
022import com.google.common.cache.CacheLoader;
023import com.google.common.cache.LoadingCache;
024import org.apache.jena.rdf.model.Model;
025
026import java.util.Objects;
027import java.util.Set;
028import java.util.concurrent.ExecutionException;
029import java.util.concurrent.TimeUnit;
030
031public class CachingConciseBoundedDescriptionGenerator implements ConciseBoundedDescriptionGenerator {
032
033    private ConciseBoundedDescriptionGenerator delegatee;
034
035    private static class CacheKey {
036        private final String resource;
037        private final int depth;
038        private final boolean withTypesForLeafs;
039
040        CacheKey(String resource, int depth, boolean withTypesForLeafs) {
041            this.resource = resource;
042            this.depth = depth;
043            this.withTypesForLeafs = withTypesForLeafs;
044        }
045
046        static CacheKey of(String resource, int depth, boolean withTypesForLeafs) {
047            return new CacheKey(resource, depth, withTypesForLeafs);
048        }
049
050        @Override
051        public boolean equals(Object o) {
052            if (this == o) return true;
053            if (o == null || getClass() != o.getClass()) return false;
054            CacheKey cacheKey = (CacheKey) o;
055            return depth == cacheKey.depth &&
056                    withTypesForLeafs == cacheKey.withTypesForLeafs &&
057                    Objects.equals(resource, cacheKey.resource);
058        }
059
060        @Override
061        public int hashCode() {
062            return Objects.hash(resource, depth, withTypesForLeafs);
063        }
064    }
065
066    private LoadingCache<CacheKey, Model> cache = CacheBuilder.newBuilder()
067            .maximumSize(100)
068            .expireAfterWrite(1, TimeUnit.HOURS)
069            .build(
070                    new CacheLoader<CacheKey, Model>() {
071                        public Model load(CacheKey key) {
072                            return delegatee.getConciseBoundedDescription(key.resource, key.depth, key.withTypesForLeafs);
073                        }
074                    });
075
076    public CachingConciseBoundedDescriptionGenerator(ConciseBoundedDescriptionGenerator cbdGen) {
077        this.delegatee = cbdGen;
078    }
079
080    /* (non-Javadoc)
081     * @see org.dllearner.kb.sparql.ConciseBoundedDescriptionGenerator#getConciseBoundedDescription(java.lang.String, int, boolean)
082     */
083    @Override
084    public Model getConciseBoundedDescription(String resource, int depth, boolean withTypesForLeafs) {
085        try {
086            return cache.get(CacheKey.of(resource, depth, withTypesForLeafs));
087        } catch (ExecutionException e) {
088            throw new RuntimeException("Failed to computed cached CBD", e);
089        }
090    }
091
092    @Override
093    public void setAllowedPropertyNamespaces(Set<String> namespaces) {
094        delegatee.setAllowedPropertyNamespaces(namespaces);
095    }
096
097    /* (non-Javadoc)
098     * @see org.dllearner.kb.sparql.ConciseBoundedDescriptionGenerator#setAllowedObjectNamespaces(java.util.Set)
099     */
100    @Override
101    public void setAllowedObjectNamespaces(Set<String> namespaces) {
102        delegatee.setAllowedObjectNamespaces(namespaces);
103    }
104
105    @Override
106    public void setAllowedClassNamespaces(Set<String> namespaces) {
107        delegatee.setAllowedClassNamespaces(namespaces);
108    }
109
110    @Override
111    public void setIgnoredProperties(Set<String> properties) {
112        delegatee.setIgnoredProperties(properties);
113    }
114}