org.apache.stanbol.entityhub.core.mapping.DefaultFieldMapperImpl Maven / Gradle / Ivy
/*
* 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.core.mapping;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import org.apache.stanbol.entityhub.servicesapi.defaults.DataTypeEnum;
import org.apache.stanbol.entityhub.servicesapi.mapping.FieldMapper;
import org.apache.stanbol.entityhub.servicesapi.mapping.FieldMapping;
import org.apache.stanbol.entityhub.servicesapi.model.Representation;
import org.apache.stanbol.entityhub.servicesapi.model.Text;
import org.apache.stanbol.entityhub.servicesapi.model.ValueFactory;
import org.apache.stanbol.entityhub.servicesapi.query.TextConstraint;
import org.apache.stanbol.entityhub.servicesapi.query.ValueConstraint;
import org.apache.stanbol.entityhub.servicesapi.query.Constraint.ConstraintType;
import org.apache.stanbol.entityhub.servicesapi.util.PatternUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is only an intermediate solution just to have the functionality.
* This needs to be refactored! This is something similar to a semantic lifting
* work flow that could used schema translation, reasoning ...
* The goal is to build a simple Module that supports basics things (like the
* stuff provided by this implementation) and that allow other implementations
* to do the advanced stuff.
* Currently I hope, that when the functionality is in place it is easier to
* see what a good design for this part of the Entityhub would be.
* TODO: refactoring (see above comment)
* @author Rupert Westenthaler
*
*/
public class DefaultFieldMapperImpl implements FieldMapper, Cloneable {
private final Logger log = LoggerFactory.getLogger(DefaultFieldMapperImpl.class);
private final Set mappings;
// private final Map> ignoreFieldMap;
// private final Map> ignoreWildcardMap;
private final Map> fieldMap;
private final Map> wildcardMap;
private Collection unmodMappings;
private ValueConverterFactory valueConverter;
//private Map mappings = Collections.synchronizedMap(new HashMap());
public DefaultFieldMapperImpl(ValueConverterFactory valueConverter) {
super();
mappings = new HashSet();
unmodMappings = Collections.unmodifiableCollection(mappings);
fieldMap = new HashMap>();
wildcardMap = new HashMap>();
if(valueConverter == null){
throw new IllegalArgumentException("The parsed ValueConverterFactory MUST NOT be NULL");
}
this.valueConverter = valueConverter;
// ignoreFieldMap = new HashMap>();
// ignoreWildcardMap = new HashMap>();
}
/**
* Internally used by clone
* @param fieldMap
* @param wildcardMap
*/
private DefaultFieldMapperImpl(ValueConverterFactory valueConverter,Set mappings,Map> fieldMap, Map> wildcardMap){
this(valueConverter);
this.mappings.addAll(mappings);
this.fieldMap.putAll(fieldMap);
this.wildcardMap.putAll(wildcardMap);
}
/**
* Getter for all the defined Mappings for a given field name
* @param field the name of the field
* @return all the active Mappings
*/
protected List getMappings(String field){
final List fieldMappings = new ArrayList();
//first search the fieldMappings
Collection tmp = fieldMap.get(field);
if(tmp != null){
fieldMappings.addAll(tmp);
}
//now iterate over the Wildcard Mappings
for(Entry> entry : wildcardMap.entrySet()){
if(entry.getKey().matcher(field).find()){
fieldMappings.addAll(entry.getValue());
}
}
Collections.sort(fieldMappings, FieldMappingUtils.FIELD_MAPPING_COMPARATOR);
return fieldMappings;
}
/* (non-Javadoc)
* @see org.apache.stanbol.entityhub.servicesapi.mapping.FieldMapper#addMapping(org.apache.stanbol.entityhub.servicesapi.mapping.FieldMapping)
*/
public void addMapping(FieldMapping mapping){
if(mapping == null){
return;
}
if(mappings.add(mapping)){
if(mapping.usesWildcard()){
Pattern fieldPattern = mapping.getRegexPattern();
synchronized (wildcardMap) {
Set fieldPatternMappings = wildcardMap.get(fieldPattern);
if(fieldPatternMappings == null){
fieldPatternMappings = new HashSet();//new TreeSet(FieldMappingUtils.FIELD_MAPPING_COMPARATOR);
wildcardMap.put(fieldPattern, fieldPatternMappings);
}
fieldPatternMappings.add(mapping);
}
} else {
String fieldName = mapping.getFieldPattern();
synchronized (fieldMap) {
Set fieldPatternMappings = fieldMap.get(fieldName);
if(fieldPatternMappings == null){
fieldPatternMappings = new HashSet();//new TreeSet(FieldMappingUtils.FIELD_MAPPING_COMPARATOR);
fieldMap.put(fieldName, fieldPatternMappings);
}
fieldPatternMappings.add(mapping);
}
}
} //else already present -> nothing todo
}
public Collection getMappings(){
return unmodMappings;
}
// private static String getPrefix(String fieldPattern){
// return fieldPattern.split("[\\?\\*]")[0];
// }
/* (non-Javadoc)
* @see org.apache.stanbol.entityhub.servicesapi.mapping.FieldMapper#removeFieldMapping(org.apache.stanbol.entityhub.servicesapi.mapping.FieldMapping)
*/
public void removeFieldMapping(FieldMapping mapping){
if(mapping == null){
return;
}
if(mappings.remove(mapping)){
if(mapping.usesWildcard()){
Pattern fieldPattern = mapping.getRegexPattern();
synchronized (wildcardMap) {
Collection fieldPatternMappings = wildcardMap.get(fieldPattern);
if(fieldPatternMappings != null){
if(fieldPatternMappings.remove(mapping) && fieldPatternMappings.isEmpty()){
//clean up the prefix if last value is removed
wildcardMap.remove(fieldPattern);
}
}
}
} else {
String fieldPattern = mapping.getFieldPattern();
synchronized (fieldMap) {
Collection fieldPatternMappings = fieldMap.get(fieldPattern);
if(fieldPatternMappings != null){
if(fieldPatternMappings.remove(mapping) && fieldPatternMappings.isEmpty()){
//clean up the prefix if last value is removed
fieldMap.remove(fieldPattern);
}
}
}
}
} //else nothing todo
}
/**
* Removes the FieldMapping based on the fieldPattern
* @param fieldPattern the field pattern
*/
public void removeFieldMapping(String fieldPattern){
if(fieldPattern == null || fieldPattern.length()<1){
return;
}
if(PatternUtils.usesWildCard(fieldPattern)){
Pattern pattern = Pattern.compile(PatternUtils.wildcardToRegex(fieldPattern,true));
synchronized (wildcardMap) {
wildcardMap.remove(pattern);
}
} else {
synchronized (fieldMap) {
fieldMap.remove(fieldPattern);
}
}
}
/* (non-Javadoc)
* @see org.apache.stanbol.entityhub.servicesapi.mapping.FieldMapper#applyMappings(org.apache.stanbol.entityhub.servicesapi.model.Representation, org.apache.stanbol.entityhub.servicesapi.model.Representation)
*/
public Representation applyMappings(Representation source, Representation target, ValueFactory valueFactory) {
Collection fields = new HashSet();
for(Iterator fieldIt = source.getFieldNames();fieldIt.hasNext();){
fields.add(fieldIt.next());
}
for(String field : fields){
// log.info(" > process field: "+field);
//get the active Mappings
List activeMappings = getMappings(field);
if(!activeMappings.isEmpty()){
//get all the values (store them in an Collection, because we need them more than once)
Collection