/* * 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.enhancer.engines.dereference; import static org.apache.stanbol.enhancer.engines.dereference.DereferenceConstants.DEREFERENCE_ENTITIES_LANGUAGES; import static org.apache.stanbol.enhancer.engines.dereference.DereferenceConstants.NO_LANGUAGE_KEY; import java.io.ObjectInputStream.GetField; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import org.apache.clerezza.commons.rdf.IRI; import org.apache.commons.lang.StringUtils; import org.apache.stanbol.commons.namespaceprefix.NamespaceMappingUtils; import org.apache.stanbol.commons.namespaceprefix.NamespacePrefixService; import org.apache.stanbol.commons.stanboltools.offline.OfflineMode; import org.apache.stanbol.enhancer.servicesapi.helper.EnhancementEngineHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DereferenceContext { protected final Logger log = LoggerFactory.getLogger(getClass()); protected final static String INTERNAL_CONTENT_LANGUAGES = "internal.dereference.contentlanguages"; protected final static String INTERNAL_ACCEPT_LANGUAGES = "internal.dereference.acceptlanguages"; protected final EntityDereferenceEngine engine; protected final Map<String,Object> enhancementProps; /** * The {@link OfflineMode} status */ private boolean offlineMode; /** * Read-only set with literal languages defined in the context. */ private Set<String> contextLanguages; /** * Read-only set with literal languages to be dereferenced. This is the * union over {@link #contextLanguages} and {@link #getConfig()}. * {@link DereferenceEngineConfig#getLanaguages() getLanaguages()} */ private Set<String> languages; private List<String> fields; private String program; private HashSet<IRI> entityReferences; /** * Create a new DereferenceContext. * @param offlineMode the {@link OfflineMode} state * @param ep The enhancement properties * @throws DereferenceConfigurationException if the parsed enhancement * propertied contain an invalid configuration */ @SuppressWarnings("unchecked") protected DereferenceContext(EntityDereferenceEngine engine, Map<String,Object> ep) throws DereferenceConfigurationException { this.engine = engine; this.enhancementProps = ep; parseLanguages(ep == null ? null : ep.get(DEREFERENCE_ENTITIES_LANGUAGES), ep == null ? null : (Collection<String>)ep.get(INTERNAL_CONTENT_LANGUAGES), ep == null ? null : (Collection<String>)ep.get(INTERNAL_ACCEPT_LANGUAGES)); parseFields(ep == null ? null : ep.get(DereferenceConstants.DEREFERENCE_ENTITIES_FIELDS)); parseLDPath(ep == null ? null : ep.get(DereferenceConstants.DEREFERENCE_ENTITIES_LDPATH)); parseEntityReferences(ep == null ? null : ep.get(DereferenceConstants.ENTITY_REFERENCES)); //call the initialisation callback initialise(); } private void parseEntityReferences(Object value) throws DereferenceConfigurationException { Collection<String> entityRefProps; try{ entityRefProps = EnhancementEngineHelper.parseConfigValues(value, String.class); } catch (IllegalStateException e){ throw new DereferenceConfigurationException(e, engine.getDereferencer().getClass(), DereferenceConstants.ENTITY_REFERENCES); } //start with the references present in the config this.entityReferences = new HashSet<IRI>(getConfig().getEntityReferences()); if(entityRefProps != null && !entityRefProps.isEmpty()){ NamespacePrefixService nps = engine.getConfig().getNsPrefixService(); for(String prop : entityRefProps){ if(!StringUtils.isBlank(prop)){ try { entityReferences.add(new IRI( NamespaceMappingUtils.getConfiguredUri(nps, prop))); } catch(IllegalArgumentException e){ throw new DereferenceConfigurationException(e, engine.getDereferencer().getClass(), DereferenceConstants.ENTITY_REFERENCES); } } } } } /** * Parses the {@link DereferenceConstants#DEREFERENCE_ENTITIES_LANGUAGES} * from the parsed value, merges content- and accept-languages and finally * calls {@link #initLiteralLanguages(Set)} with the resulting set * @param value the value of the * {@link DereferenceConstants#DEREFERENCE_ENTITIES_LANGUAGES} key * @param the content languages or <code>null</code> if * {@link DereferenceConstants#FILTER_CONTENT_LANGUAGES} is deactivated * @param the accept languages or <code>null</code> if * {@link DereferenceConstants#FILTER_ACCEPT_LANGUAGES} is deactivated * @throws DereferenceConfigurationException if the parsed value is not a * valid configuration */ private void parseLanguages(Object value, Collection<String> contentLanguages, Collection<String> acceptLanguages) throws DereferenceConfigurationException { Set<String> languages; if(value == null){ languages = null; } else { languages = new HashSet<String>(); if(value instanceof String){ String lang = (String) value; addLanguage(languages, lang); } else if(value instanceof Collection<?>){ for(Object lang : (Collection<?>)value){ if(lang instanceof String){ addLanguage(languages, (String)lang); } } } if(languages.isEmpty()){ languages = null; } } if(contentLanguages != null && !contentLanguages.isEmpty()){ if(languages == null){ languages = new HashSet<String>(); } languages.addAll(contentLanguages); } if(acceptLanguages != null && !acceptLanguages.isEmpty()){ if(languages == null){ languages = new HashSet<String>(); } languages.addAll(acceptLanguages); } //set the contextLanguages field if(languages == null){ this.contextLanguages = Collections.emptySet(); } else { this.contextLanguages = Collections.unmodifiableSet(languages); } //merge the languages with those of the config and set the languages field Set<String> merged; Collection<String> configLangs = getConfig().getLanaguages(); if(languages == null && configLangs == null){ merged = null; } else if(configLangs == null){ merged = languages; } else { merged = new HashSet<String>(configLangs); if(languages != null){ merged.addAll(languages); } } this.languages = merged; } /** * Parsed the language from the language string and adds it to the languages * set. This will convert languages to lower case and also converts empty * values as well as the {@link DereferenceConstants#NO_LANGUAGE_KEY} to * <code>null</code> (indicating labels without any language) * @param languages * @param lang */ private void addLanguage(Set<String> languages, String lang) { if(StringUtils.isBlank(lang) || NO_LANGUAGE_KEY.equalsIgnoreCase(lang)){ languages.add(null); } else { languages.add(lang.toLowerCase(Locale.ROOT)); } } /** * Parsed the {@link DereferenceConstants#DEREFERENCE_ENTITIES_FIELDS} * from the parsed value and calls {@link #initDereferencedFields(List)} with * the parsed value * @param value the value * @throws DereferenceConfigurationException if the parsed value is not a * valid configuration */ private void parseFields(Object value) throws DereferenceConfigurationException{ List<String> fields; if(value instanceof String && !StringUtils.isBlank((String)value)){ fields = Collections.singletonList((String)value); } else if(value instanceof Collection<?>){ fields = new ArrayList<String>(((Collection<?>)value).size()); for(Object field : (Collection<?>)value){ if(field != null && field instanceof String && !StringUtils.isBlank((String)field)){ fields.add((String)field); } // else ignore } } else { fields = null; } this.fields = fields; } /** * Parsed the {@link DereferenceConstants#DEREFERENCE_ENTITIES_LDPATH} * from the parsed value and calls {@link #initLdPathProgram(String)} with * the parsed value * @param value the value * @throws DereferenceConfigurationException if the parsed value is not a * valid configuration */ private void parseLDPath(Object value) throws DereferenceConfigurationException { String program; if(value instanceof String && !StringUtils.isBlank((String)value)){ program = (String)value; } else if(value instanceof Collection<?>){ StringBuilder sb = new StringBuilder(); for(Object field : (Collection<?>)value){ if(field != null && field instanceof String && !StringUtils.isBlank((String)field)){ sb.append((String)field).append('\n'); } // else ignore } program = sb.length() > 0 ? sb.toString() : null; } else { program = null; } this.program = program; } /** * Allows to set the offline mode state */ protected final void setOfflineMode(boolean state){ this.offlineMode = state; } /** * If the {@link OfflineMode} is active. If active Dereferencers are not * allowed access remote resources for dereferencing Entities. * @return the offline mode status */ public final boolean isOfflineMode() { return offlineMode; } /** * Context specific DerefernecedField configuration * @return the context specific DereferencedField configuration or * <code>null</code> if none */ public final List<String> getFields() { return fields; } /** * Initialisation callback for the DereferenceContext. This is called by * the constructor after the {@link #enhancementProps} are set and * {@link #getLanguages()}, {@link #getFields()} and * {@link #getLdPathProgram()} are initialised.<p> * The default implementation is empty. */ protected void initialise(){ } /** * Context specific LDPath program * @return the context specific LDPath program or <code>null</code> if none */ public final String getLdPathProgram() { return program; } /** * The property URIs that may refer to Entities that need to be dereferenced. * This is the union view over properties parsed as EnhancementProperties * with properties configured with the engine * @return the entity reference properties * @see DereferenceEngineConfig#getEntityReferences() */ public HashSet<IRI> getEntityReferences() { return entityReferences; } /** * Getter for the languages that should be dereferenced. If * empty all languages should be included. This is the union over * Languages enabled in the context and * {@link #getConfig()}.{@link DereferenceEngineConfig#getLanaguages() * getLanaguages()} * @return the languages for literals that should be dereferenced. */ public final Set<String> getLanguages() { return languages; } /** * Set of languages enabled via the context. This does not include languages * enabled in the {@link DereferenceEngineConfig} * @return the set of languages enabled via the context. */ protected final Set<String> getContextLanguages(){ return contextLanguages; } /** * Getter for the Enhancement Properties for this Context. * @return the Enhancement Properties */ protected final Map<String,Object> getEnhancementProps() { return enhancementProps; } /** * Getter for the Dereference Engine Configuration * @return the dereference configuration */ public final DereferenceEngineConfig getConfig() { return engine.getConfig(); } /** * The EntityDereferencer this context is built for * @return the entity dereferencer */ public final EntityDereferencer getDereferencer(){ return engine.getDereferencer(); } }