/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * * 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 org.apache.stanbol.entityhub.indexing.core.processor; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Iterator; import java.util.Map; import org.apache.commons.io.IOUtils; import org.apache.commons.io.LineIterator; import org.apache.stanbol.commons.namespaceprefix.NamespacePrefixService; import org.apache.stanbol.entityhub.core.mapping.FieldMappingUtils; import org.apache.stanbol.entityhub.core.model.InMemoryValueFactory; import org.apache.stanbol.entityhub.indexing.core.EntityProcessor; import org.apache.stanbol.entityhub.indexing.core.config.IndexingConfig; import org.apache.stanbol.entityhub.servicesapi.mapping.FieldMapper; import org.apache.stanbol.entityhub.servicesapi.model.Representation; import org.apache.stanbol.entityhub.servicesapi.model.ValueFactory; public class FiledMapperProcessor implements EntityProcessor{ public static final String PARAM_MAPPINGS = "mappings"; public static final String PARAM_VALUE_FACTORY = "valueFactory"; public static final String DEFAULT_MAPPINGS_FILE_NAME = "fieldMappings.txt"; private FieldMapper mapper; private ValueFactory vf; private NamespacePrefixService nsPrefixService; /** * This Constructor relays on that {@link #setConfiguration(Map)} is called * afterwards! */ public FiledMapperProcessor(){ this(null,null); } /** * Internally used to initialise the {@link ValueFactory} * @param vf the value factory or <code>null</code> to use the {@link InMemoryValueFactory}. */ private FiledMapperProcessor(NamespacePrefixService nps, ValueFactory vf){ setValueFactory(vf); this.nsPrefixService = nps; } public FiledMapperProcessor(FieldMapper mapper, NamespacePrefixService nps, ValueFactory vf){ this(nps,vf); if(mapper == null){ throw new IllegalArgumentException("The parsed FieldMapper MUST NOT be NULL!"); } else if(mapper.getMappings().isEmpty()){ throw new IllegalStateException("The parsed field mappings MUST contain at least a single valid mapping!"); } this.mapper = mapper; } public FiledMapperProcessor(Iterator<String> mappings, NamespacePrefixService nps, ValueFactory vf){ this(nps, vf); if(mappings == null){ throw new IllegalArgumentException("The parsed field mappings MUST NOT be NULL!"); } mapper = FieldMappingUtils.createDefaultFieldMapper(mappings,nsPrefixService); if(mapper.getMappings().isEmpty()){ throw new IllegalStateException("The parsed field mappings MUST contain at least a single valid mapping!"); } } public FiledMapperProcessor(InputStream mappings, NamespacePrefixService nps, ValueFactory vf) throws IOException{ this(nps, vf); if(mappings == null){ throw new IllegalArgumentException("The parsed field mappings MUST NOT be NULL!"); } this.mapper = createMapperFormStream(mappings,nsPrefixService); } @Override public Representation process(Representation source) { if(mapper == null){ throw new IllegalStateException("The mapper is not initialised. One must call setConfiguration to configure the FieldMapper!"); } if(source == null){ return null; } else { return mapper.applyMappings(source, vf.createRepresentation(source.getId()), vf); } } /** * used by the different constructors to init the {@link ValueFactory} * @param vf the value factory or <code>null</code> to use the default */ private void setValueFactory(ValueFactory vf) { if(vf == null){ this.vf = InMemoryValueFactory.getInstance(); } else { this.vf = vf; } } @Override public void close() { //nothing todo } @Override public void initialise() { //nothing todo } @Override public boolean needsInitialisation() { return false; } @Override public void setConfiguration(Map<String,Object> config) { IndexingConfig indexingConfig = (IndexingConfig)config.get(IndexingConfig.KEY_INDEXING_CONFIG); nsPrefixService = indexingConfig.getNamespacePrefixService(); Object value = config.get(PARAM_MAPPINGS); if(value == null || value.toString().isEmpty()){ //use the mappings configured for the Index this.mapper = FieldMappingUtils.createDefaultFieldMapper( indexingConfig.getIndexFieldConfiguration()); } else { //load (other) mappings based on the provided mappings parameter //final File file = new File(indexingConfig.getConfigFolder(),value.toString()); File mappings = indexingConfig.getConfigFile(value.toString()); if(mappings != null){ try { InputStream in = new FileInputStream(mappings); this.mapper = createMapperFormStream(in,nsPrefixService); IOUtils.closeQuietly(in); } catch (IOException e) { throw new IllegalArgumentException("Unable to access FieldMapping file "+ value+" not found in configuration directory "+ indexingConfig.getConfigFolder()); } } else { throw new IllegalArgumentException("FieldMapping file "+ value+" not found in configuration directory "+ indexingConfig.getConfigFolder()); } } //TODO: get the valueFactory form the config (currently an InMemory is //create by the default constructor! } /** * Utility that allows to create a FieldMapper form an inputStream. * It uses {@link IOUtils#lineIterator(InputStream, String)} and parses it * to {@link FieldMappingUtils#createDefaultFieldMapper(Iterator)} * @param in the stream to read the mappings from * @throws IOException on any error while reading the data from the stream */ private static FieldMapper createMapperFormStream(final InputStream in, NamespacePrefixService nps) throws IOException { return FieldMappingUtils.createDefaultFieldMapper(new Iterator<String>() { LineIterator it = IOUtils.lineIterator(in, "UTF-8"); @Override public boolean hasNext() { return it.hasNext(); } @Override public String next() { return it.nextLine(); } @Override public void remove() { it.remove(); } },nps); } }