/** * * Copyright * 2009-2015 Jayway Products AB * 2016-2017 Föreningen Sambruk * * Licensed under AGPL, Version 3.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.gnu.org/licenses/agpl.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package se.streamsource.streamflow.web.infrastructure.plugin.address; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.NamedList; import org.apache.solr.core.SolrCore; import org.qi4j.api.configuration.Configuration; import org.qi4j.api.injection.scope.Service; import org.qi4j.api.injection.scope.Structure; import org.qi4j.api.injection.scope.This; import org.qi4j.api.mixin.Mixins; import org.qi4j.api.service.Activatable; import org.qi4j.api.service.ServiceComposite; import org.qi4j.api.structure.Module; import org.qi4j.api.value.ValueBuilder; import org.restlet.Client; import org.restlet.data.Protocol; import org.restlet.data.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import se.streamsource.dci.restlet.client.CommandQueryClient; import se.streamsource.dci.restlet.client.CommandQueryClientFactory; import se.streamsource.dci.restlet.client.NullResponseHandler; import se.streamsource.streamflow.server.plugin.address.StreetAddressLookup; import se.streamsource.streamflow.server.plugin.address.StreetList; import se.streamsource.streamflow.server.plugin.address.StreetValue; import se.streamsource.streamflow.web.infrastructure.index.EmbeddedSolrService; import se.streamsource.streamflow.web.infrastructure.plugin.StreetAddressLookupConfiguration; import java.util.ArrayList; import java.util.List; /** * Service that looks up street addresses in a REST plugin */ @Mixins(StreetAddressLookupService.Mixin.class) public interface StreetAddressLookupService extends ServiceComposite, StreetAddressLookup, Configuration, Activatable { class Mixin implements StreetAddressLookup, Activatable { @Service private EmbeddedSolrService solr; @This Configuration<StreetAddressLookupConfiguration> config; @Structure Module module; private CommandQueryClient cqc; private SolrCore core; Logger log = LoggerFactory.getLogger( StreetAddressLookupService.class ); public void activate() throws Exception { config.configuration(); if (config.configuration().enabled().get()) { Reference serverRef = new Reference( config.configuration().url().get() ); Client client = new Client( Protocol.HTTP ); client.start(); cqc = module.objectBuilderFactory().newObjectBuilder(CommandQueryClientFactory.class).use( client, new NullResponseHandler() ).newInstance().newClient( serverRef ); core = solr.getSolrCore( "sf-streetcache" ); if( config.configuration().forceReload().get() || config.configuration().lastLoaded().get() == 0 || ( (config.configuration().lastLoaded().get() - System.currentTimeMillis() ) > config.configuration().loadFrequence().get() ) ) { reindex(); if( core != null ) core.close(); if( config.configuration().forceReload().get()) { config.configuration().forceReload().set( false ); config.save(); } } } } public void passivate() throws Exception { } public StreetList lookup(StreetValue streetTemplate) { if( (config.configuration().lastLoaded().get() - System.currentTimeMillis() ) > config.configuration().loadFrequence().get() ) { reindex(); } ValueBuilder<StreetList> streetListBuilder = module.valueBuilderFactory().newValueBuilder( StreetList.class ); try { int limit = config.configuration().limit().get(); if (config.configuration().minkeywordlength().get() <= streetTemplate.address().get().length()) { NamedList list = new NamedList(); list.add( "q", "address:" + streetTemplate.address().get().toLowerCase().trim().replace( " ", "*" ) + "*" ); QueryResponse query = solr.getSolrServer( "sf-streetcache" ).query( SolrParams.toSolrParams( list ) ); SolrDocumentList results = query.getResults(); ValueBuilder<StreetValue> streetValueBuilder = module.valueBuilderFactory().newValueBuilder( StreetValue.class ); int count = 1; for(SolrDocument document : results ) { if( limit != -1 && limit < count ) { break; } streetValueBuilder.prototype().address().set( (String)document.get( "address" ) ); streetValueBuilder.prototype().area().set( (String)document.get( "area" ) ); streetListBuilder.prototype().streets().get().add( streetValueBuilder.newInstance() ); count++; } } return streetListBuilder.newInstance(); } catch( Throwable e) { log.error( "Could not get address list", e ); // Return empty list return module.valueBuilderFactory().newValue(StreetList.class); } } public void reindex() { // make sure plugin is enabled before running reindex! if (config.configuration().enabled().get()) { List<SolrInputDocument> added = new ArrayList<SolrInputDocument>(); try { StreetValue streetValue = module.valueBuilderFactory().newValueBuilder( StreetValue.class ).prototype(); streetValue.address().set( "%" ); StreetList streets = cqc.query( config.configuration().url().get(), StreetList.class, streetValue.buildWith().newInstance() ); for (StreetValue street : streets.streets().get()) { SolrInputDocument document = new SolrInputDocument(); document.addField( "address", street.address().get() ); document.addField( "area", street.area().get() ); added.add( document ); } try { // empty the index solr.getSolrServer( "sf-streetcache" ).deleteByQuery( "*:*" ); solr.getSolrServer( "sf-streetcache" ).add( added ); } finally { // do not commit explicitly - let solr server do autocommit //solr.getSolrServer( "sf-streetcache" ).commit( false, false ); config.configuration().lastLoaded().set( System.currentTimeMillis() ); config.save(); } } catch (Throwable e) { log.error( "Could not create/update solr index for street address lookup.", e ); } } } } }