/* * 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.solr.handler.dataimport.config; import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.solr.handler.dataimport.DataImporter; import org.apache.solr.handler.dataimport.DocBuilder; import org.apache.solr.schema.IndexSchema; import org.apache.solr.schema.SchemaField; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Element; /** * <p> * Mapping for data-config.xml * </p> * <p> * Refer to <a * href="http://wiki.apache.org/solr/DataImportHandler">http://wiki.apache.org/solr/DataImportHandler</a> * for more details. * </p> * <p> * <b>This API is experimental and subject to change</b> * * @since solr 1.3 */ public class DIHConfiguration { private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); // TODO - remove from here and add it to entity private final String deleteQuery; private final List<Entity> entities; private final String onImportStart; private final String onImportEnd; private final String onError; private final List<Map<String, String>> functions; private final Script script; private final Map<String, Map<String,String>> dataSources; private final PropertyWriter propertyWriter; private final IndexSchema schema; private final Map<String,SchemaField> lowerNameVsSchemaField; public DIHConfiguration(Element element, DataImporter di, List<Map<String,String>> functions, Script script, Map<String,Map<String,String>> dataSources, PropertyWriter pw) { schema = di.getSchema(); lowerNameVsSchemaField = null == schema ? Collections.<String,SchemaField>emptyMap() : loadSchemaFieldMap(); this.deleteQuery = ConfigParseUtil.getStringAttribute(element, "deleteQuery", null); this.onImportStart = ConfigParseUtil.getStringAttribute(element, "onImportStart", null); this.onImportEnd = ConfigParseUtil.getStringAttribute(element, "onImportEnd", null); this.onError = ConfigParseUtil.getStringAttribute(element, "onError", null); List<Entity> modEntities = new ArrayList<>(); List<Element> l = ConfigParseUtil.getChildNodes(element, "entity"); boolean docRootFound = false; for (Element e : l) { Entity entity = new Entity(docRootFound, e, di, this, null); Map<String, EntityField> fields = gatherAllFields(di, entity); verifyWithSchema(fields); modEntities.add(entity); } this.entities = Collections.unmodifiableList(modEntities); if(functions==null) { functions = Collections.emptyList(); } List<Map<String, String>> modFunc = new ArrayList<>(functions.size()); for(Map<String, String> f : functions) { modFunc.add(Collections.unmodifiableMap(f)); } this.functions = Collections.unmodifiableList(modFunc); this.script = script; this.dataSources = Collections.unmodifiableMap(dataSources); this.propertyWriter = pw; } private void verifyWithSchema(Map<String,EntityField> fields) { Map<String,SchemaField> schemaFields = null; if (schema == null) { schemaFields = Collections.emptyMap(); } else { schemaFields = schema.getFields(); } for (Map.Entry<String,SchemaField> entry : schemaFields.entrySet()) { SchemaField sf = entry.getValue(); if (!fields.containsKey(sf.getName())) { if (sf.isRequired()) { LOG.info(sf.getName() + " is a required field in SolrSchema . But not found in DataConfig"); } } } for (Map.Entry<String,EntityField> entry : fields.entrySet()) { EntityField fld = entry.getValue(); SchemaField field = getSchemaField(fld.getName()); if (field == null && !isSpecialCommand(fld.getName())) { LOG.info("The field :" + fld.getName() + " present in DataConfig does not have a counterpart in Solr Schema"); } } } private Map<String,EntityField> gatherAllFields(DataImporter di, Entity e) { Map<String,EntityField> fields = new HashMap<>(); if (e.getFields() != null) { for (EntityField f : e.getFields()) { fields.put(f.getName(), f); } } for (Entity e1 : e.getChildren()) { fields.putAll(gatherAllFields(di, e1)); } return fields; } private Map<String,SchemaField> loadSchemaFieldMap() { Map<String, SchemaField> modLnvsf = new HashMap<>(); for (Map.Entry<String, SchemaField> entry : schema.getFields().entrySet()) { modLnvsf.put(entry.getKey().toLowerCase(Locale.ROOT), entry.getValue()); } return Collections.unmodifiableMap(modLnvsf); } public SchemaField getSchemaField(String caseInsensitiveName) { SchemaField schemaField = null; if(schema!=null) { schemaField = schema.getFieldOrNull(caseInsensitiveName); } if (schemaField == null) { schemaField = lowerNameVsSchemaField.get(caseInsensitiveName.toLowerCase(Locale.ROOT)); } return schemaField; } public String getDeleteQuery() { return deleteQuery; } public List<Entity> getEntities() { return entities; } public String getOnImportStart() { return onImportStart; } public String getOnImportEnd() { return onImportEnd; } public String getOnError() { return onError; } public List<Map<String,String>> getFunctions() { return functions; } public Map<String,Map<String,String>> getDataSources() { return dataSources; } public Script getScript() { return script; } public PropertyWriter getPropertyWriter() { return propertyWriter; } public IndexSchema getSchema() { return schema; } public static boolean isSpecialCommand(String fld) { return DocBuilder.DELETE_DOC_BY_ID.equals(fld) || DocBuilder.DELETE_DOC_BY_QUERY.equals(fld) || DocBuilder.DOC_BOOST.equals(fld) || DocBuilder.SKIP_DOC.equals(fld) || DocBuilder.SKIP_ROW.equals(fld); } }