You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stanbol.apache.org by sf...@apache.org on 2010/12/12 16:02:37 UTC
svn commit: r1044829 [3/12] - in /incubator/stanbol/trunk/rick/generic:
core/src/main/java/eu/iksproject/rick/core/impl/
core/src/main/java/eu/iksproject/rick/core/mapping/
core/src/main/java/eu/iksproject/rick/core/model/
core/src/main/java/eu/iksproj...
Modified: incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/impl/RickImpl.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/impl/RickImpl.java?rev=1044829&r1=1044828&r2=1044829&view=diff
==============================================================================
--- incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/impl/RickImpl.java (original)
+++ incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/impl/RickImpl.java Sun Dec 12 15:02:34 2010
@@ -55,461 +55,461 @@ import eu.iksproject.rick.servicesapi.ya
@Component()
@Service
public final class RickImpl implements Rick, ServiceListener {
-
- private final Logger log = LoggerFactory.getLogger(RickImpl.class);
- /**
- * The OSGI component context of the Rick
- */
- private ComponentContext context;
- /**
- * The field mapper holding global mappings that are used for mapping
- * representations of entities for any referenced sites
- */
- protected FieldMapper fieldMapper;
-
- /**
- * The yard where this Rick instance stores its data
- * TODO: this reference is currently initialised in the activate method.
- * however there are some issues with that.
- * <ul>
- * <li> If this Component is activated, before this yard is active, the
- * activate method throws an Exception and is therefore in the
- * "unsatisfied" state.
- * <li> If now the needed Yard is configured this component gets not notified
- * <li> However defining a Reference is also not possible, because it would
- * be nice to be able to change the Rick-Yard (e.g. to change the data
- * set of the Rick at runtime)
- * <li> I could register a {@link ServiceListener} in the activate method.
- * But I am not sure if it is allowed to have an active Service Listener
- * on an component that is in the "unsatisfied" state.
- * </ul>
- */
- protected Yard rickYard; //reference initialised in the activate method
- /*
- * TODO: The YardManager is currently not used.
- */
- @Reference // 1..1, static
- protected YardManager yardManager;
- /**
- * The Configuration of the Rick
- * TODO: Maybe refactor this implementation to implement this interface or
- * to extend the {@link RickConfigurationImpl}.
- */
- @Reference // 1..1, static
- protected RickConfiguration config;
- /**
- * The site manager is used to search for entities within the Rick framework
- */
- @Reference // 1..1, static
- protected ReferencedSiteManager siteManager;
-
- private String DEFAULT_SYMBOL_PREFIX = "symbol";
- private String DEFAULT_MAPPING_PREFIX = "mapping";
- /**
- * Activates the Rick (OSGI Lifecycle method)
- * @param context the OSGI component context (stored in {@link #context})
- * @throws ConfigurationException On any error during the activation of
- * the Rick
- */
- @Activate
- protected void activate(ComponentContext context) throws ConfigurationException {
- log.info("activating Rick ...");
- if(context == null){
- throw new IllegalStateException("Unable to activate if parsed ComponentContext is NULL");
- } else {
- this.context = context;
- }
- //First check the RICK ID and
- log.info(" ... init Basic Properties");
- if(config.getID() == null || config.getID().isEmpty()){
- throw new ConfigurationException(RickConfiguration.ID, "The Rick Configuration does not define a ID for the Rick");
- } else {
- log.info(" + id: "+config.getID());
- }
- if(config.getName() == null || config.getName().isEmpty()){
- throw new ConfigurationException(RickConfiguration.NAME, "The Rick Configuration does not define a name for the Rick");
- } else {
- log.info(" + id: "+config.getName());
- }
- if(config.getDescription() != null){
- log.info(" + id: "+config.getDescription());
- }
- if(config.getRickPrefix() == null){
- throw new ConfigurationException(RickConfiguration.PREFIX, "The Rick Configuration does not define a Prefix for the Rick");
- }
- try {
- new URI(config.getRickPrefix());
- log.info(" + prefix: "+config.getRickPrefix());
- } catch (URISyntaxException e1) {
- throw new ConfigurationException(RickConfiguration.PREFIX, "The Prefix configured for the RICK is not an valied URI (prefix="+config.getRickPrefix()+")");
- }
- //next get the reference to the configured RickYard
- log.info(" ... init RickYard");
-// final ServiceReference[] refs;
-// log.info(" - search for services for "+Yard.class+" with Filter "+rickYardFilterString);
-// try {
-// refs = context.getBundleContext().getServiceReferences(
-// Yard.class.getName(),
-// rickYardFilterString);
-//
-// } catch (InvalidSyntaxException e) {
-// throw new ConfigurationException(RickConfiguration.RICK_YARD_ID, "Unable to create Filter for the RickYard based on the parsed vlaue "+config.getRickYardId(),e);
-// }
-// if(refs != null && refs.length>0){
-// log.debug(" - found "+refs.length+" Services");
-// Yard rickYard = null;
-// ServiceReference rickYardReference = null;
-// for(int i=0;i<refs.length && rickYard == null;i++){
-// rickYardReference = refs[i];
-// // I trust the OSGI framework, that the returned service implements the requested Interface
-// rickYard = (Yard)context.getBundleContext().getService(rickYardReference);
-// log.info(" + RickYard "+rickYard.getName()+" (id: "+rickYard.getId()+")");
-// }
-// //configured Yard not present -> unable to activate!
-// if(rickYard == null){
-// throw new ConfigurationException(RickConfiguration.RICK_YARD_ID, "Unable to get Yard Service for the parsed value "+config.getRickYardId());
-// }
- if(yardManager.isYard(config.getRickYardId())){
- this.rickYard = yardManager.getYard(config.getRickYardId());
- String rickYardFilterString = '('+Yard.ID+'='+config.getRickYardId()+')';
- try {
- context.getBundleContext().addServiceListener(this,rickYardFilterString);
- } catch (InvalidSyntaxException e) {
- log.warn(String.format("Unable to set Filter %s to ServiceListener for RickYard! -> add ServiceListener without Filter",
- rickYardFilterString),e);
- context.getBundleContext().addServiceListener(this);
- }
- } else {
- throw new ConfigurationException(RickConfiguration.RICK_YARD_ID, "Unable to get Yard for parsed value "+config.getRickYardId());
- }
- //at last get the FieldMappingConfig and create the FieldMappings instance
- // -> we need to do that after the init of the Rick-yard, because than we
- // can use the valueFactory of the configured Yard to create instances
- // of converted values!
- log.info(" ... init FieldMappings");
- fieldMapper = new DefaultFieldMapperImpl(ValueConverterFactory.getInstance(rickYard.getValueFactory()));
- for(String mappingString : config.getFieldMappingConfig()){
- FieldMapping mapping = FieldMappingUtils.parseFieldMapping(mappingString);
- if(mapping != null){
- log.info(" + mapping: "+mapping);
- fieldMapper.addMapping(mapping);
- }
- }
- }
- /**
- * TODO: currently only for debugging. Intended to be used for tracking
- * the state of dependencies
- */
- @Override
- public void serviceChanged(ServiceEvent event) {
- log.info("Print Service Event for "+event.getSource());
- for(String key : event.getServiceReference().getPropertyKeys()){
- log.info(" > "+key+"="+event.getServiceReference().getProperty(key));
- }
- }
-
- @Deactivate
- protected void deactivate(ComponentContext context) {
- log.info("!!deactivate");
- if(this.rickYard != null){
- //unregister the serviceListener
- this.context.getBundleContext().removeServiceListener(this);
- }
- this.fieldMapper = null;
- this.rickYard = null;
- this.context = null;
- }
-
-// @Override
-// public RickConfiguration getRickConfiguration() {
-// return config;
-// }
- @Override
- public Yard getRickYard() {
- return rickYard;
- }
-
- @Override
- public Symbol lookupSymbol(String entity) throws YardException{
- return lookupSymbol(entity,false);
- }
-
- @Override
- public Symbol lookupSymbol(String entity, boolean create) throws YardException {
- Symbol symbol = getSymbol(entity);
- if(symbol != null){
- return symbol;
- } else {
- //parsed reference was not a symbol. search for an mapped Entity
- EntityMapping entityMapping = getMappingByEntity(entity);
- if(entityMapping != null){
- symbol = getSymbol(entityMapping.getSymbolId());
- if(symbol != null){
- return symbol;
- } else {
- log.warn("Unable to find Symbol for Entity Mapping "+entityMapping+"!");
- return recoverSymbol(entityMapping.getSymbolId());
- }
- } else if(create){
- //search if the parsed reference is known by any referenced site
- // and if YES, create a new Symbol
- Sign sign = siteManager.getSign(entity);
- if(sign == null){ //id not found by any referred site
- return null;
- } else {
- return createSymbol(sign);
- }
- } else {
- return null;
- }
- }
- }
- @Override
- public Symbol createSymbol(String reference) throws IllegalStateException, IllegalArgumentException, YardException {
- Symbol symbol = getSymbol(reference);
- if(symbol == null){
- EntityMapping entityMapping = getMappingByEntity(reference);
- if(entityMapping == null){
- Sign sign = siteManager.getSign(reference);
- if(sign == null){
- return null;
- } else {
- return createSymbol(sign);
- }
- } else {
- throw new IllegalStateException("There exists already an EntityMappting for the parsed reference (mapping="+entityMapping+")");
- }
- } else {
- throw new IllegalStateException("The parsed reference is an Symbol (symbol="+symbol+")!");
- }
- }
- /**
- * Recovers an symbol based on the available {@link EntityMapping}s
- * @param symbolId the id of the Symbol
- * @return the Symbol or <code>null</code> if the recovering is unsucessfull.
- */
- private Symbol recoverSymbol(String symbolId) {
- /*
- * TODO: recover the Symbol by recreating it based on the available
- * mapped Entities
- * 1) search for all EntityMappings with this SymbolId
- * 2) get all mapped Entities
- * 3) apply the FieldMappings
- * 4) store the Symbol
- * 5) return the recovered Symbol
- */
- return null;
- }
- /*
- * @throws IllegalArgumentException if a {@link Representation} for the parsed ID is present in the
- * {@link #rickYard}, but the representation can not be wrapped by an {@link Symbol}.
- */
- @Override
- public Symbol getSymbol(String symbolId) throws IllegalArgumentException,IllegalStateException, YardException {
- if(symbolId == null || symbolId.isEmpty()){
- throw new IllegalArgumentException("The parsed symbolID MUST NOT be NULL nor empty!");
- }
- Representation rep = rickYard.getRepresentation(symbolId);
- if(rep != null){
- try {
- return new DefaultSymbolImpl(config.getRickPrefix(),rep);
- } catch(IllegalArgumentException e){
- String msg = "Unable to create Symbol based on the representation as stored in the Rick";
- log.warn(msg);
- if(log.isWarnEnabled()){
- log.warn(ModelUtils.getRepresentationInfo(rep));
- }
- throw new IllegalStateException(msg,e); //re-throw for now
- }
- } else {
- return null;
- }
- }
- protected Symbol createSymbol(Sign sign) throws YardException{
- if(sign == null){
- return null;
- }
- ReferencedSite signSite = siteManager.getReferencedSite(sign.getSignSite());
- if(signSite == null){
- log.warn("Unable to create Symbol because the ReferencedSite "+sign.getSignSite()+" for sign "+sign.getId()+" is currently not active in the RICK -> return null");
- return null;
- }
- Representation symbolRep = rickYard.create(constructResourceId(DEFAULT_SYMBOL_PREFIX));
- //and set the initial state
- symbolRep.addReference(Symbol.STATE, config.getDefaultSymbolState().getUri());
- //create a FieldMapper containing the Rick Mappings and the Site specific mappings
- //TODO: one could cache such instances
- FieldMapper siteMapper = signSite.getFieldMapper();
- FieldMapper mapper = this.fieldMapper.clone();
- for(FieldMapping siteMapping : siteMapper.getMappings()){
- mapper.addMapping(siteMapping);
- }
- Representation signRep = sign.getRepresentation();
- //TODO: As soon as MappingActivities are implemented we need to add such
- // information to the EntityMapping instance!
- mapper.applyMappings(signRep, symbolRep);
- //Second create the symbol and init the data
- Symbol symbol;
- try {
- symbol = new DefaultSymbolImpl(config.getRickPrefix(),symbolRep);
- } catch (IllegalArgumentException e){
- //unable to create Symbol based on available Information
- // -> clean up and return null;
- log.warn("Unable to create Symbol for Representation "+symbolRep.getId()+
- ", because of missing required fields! -> return null (see more Infos after Stack Trace)",e);
- if(log.isWarnEnabled()){
- log.warn(ModelUtils.getRepresentationInfo(symbolRep));
- }
- try { //try to remove the created representation in the store
- rickYard.remove(symbolRep.getId());
- } catch (YardException e1) {
- log.warn("Unable to remove Representation "+symbolRep.getId(),e1);
- }
- return null;
- }
- //Third create and init the mapped Entity
- EntityMapping entityMapping = new DefaultEntityMappingImpl(
- config.getRickPrefix(), symbolRep.getId(), signRep.getId(),
- config.getDefaultMappingState(),
- rickYard.create(constructResourceId(DEFAULT_MAPPING_PREFIX)));
- //Store the symbol and the mappedEntity in the rickYard
- rickYard.store(symbol.getRepresentation());
- rickYard.store(entityMapping.getRepresentation());
- return symbol;
-
- //we need to set the label and the description!
- }
- /**
- * Uses the Prefix as configured by the {@link #config} and the parsed
- * prefix for the type to create an unique ID for a resource.
- * @param typePrefix the prefix of the type
- * @return An id in the form <code> {@link RickConfiguration#getRickPrefix()}
- * + typePrefix + '.' + {@link ModelUtils#randomUUID()}</code>. Note that between
- * the rick prefix and the type prefix a separation chars are added
- * if it is not already defined by the {@link RickConfiguration#getRickPrefix()}
- * value.
- */
- private String constructResourceId(String typePrefix) {
- StringBuilder id = new StringBuilder();
- String prefix = config.getRickPrefix();
- if(prefix == null || prefix.isEmpty()){
- prefix = Rick.DEFAUTL_RICK_PREFIX;
- }
- id.append(prefix);
- switch(prefix.charAt(prefix.length()-1)){
- case '#':
- case ':':
- break;
- default: //add a separator
- if(prefix.startsWith("urn:")){
- id.append(':'); //use a point for now
- } else {
- id.append('/'); //use '/' instead of '#' because one needs not to escape it in GET requests
- }
- }
- if(typePrefix != null && !typePrefix.isEmpty()){
- id.append(typePrefix);
- id.append('.');
- }
- id.append(ModelUtils.randomUUID());
- return id.toString();
- }
-
-
- @Override
- public EntityMapping getMappingByEntity(String reference) throws YardException{
- if(reference == null){
- log.warn("NULL parsed as Reference -> call to getMappingByEntity ignored (return null)");
- return null;
- }
- FieldQuery fieldQuery = getQueryFavtory().createFieldQuery();
- fieldQuery.setConstraint(RdfResourceEnum.mappedEntity.getUri(), new ReferenceConstraint(reference));
- QueryResultList<String> resultList = rickYard.findReferences(fieldQuery);
- if(!resultList.isEmpty()){
- Iterator<String> resultIterator = resultList.iterator();
- EntityMapping entityMapping = getEntityMappingFromRickYard(resultIterator.next());
- if(resultIterator.hasNext()){
- log.warn("Multiple Mappings found for Entity "+reference+"!");
- log.warn(" > "+entityMapping.getId()+" -> returned instance");
- while(resultIterator.hasNext()){
- log.warn(" > "+resultIterator.next()+" -> ignored");
- }
- }
- return entityMapping;
- } else {
- log.debug("No Mapping found for Entity "+reference);
- return null;
- }
- }
- @Override
- public Collection<EntityMapping> getMappingsBySymbol(String symbol) throws YardException{
- if(symbol == null){
- log.warn("NULL parsed as Reference -> call to getMappingsBySymbol ignored (return null)");
- return null;
- }
- FieldQuery fieldQuery = getQueryFavtory().createFieldQuery();
- fieldQuery.setConstraint(RdfResourceEnum.mappedSymbol.getUri(), new ReferenceConstraint(symbol));
- QueryResultList<String> resultList = rickYard.findReferences(fieldQuery);
- Collection<EntityMapping> mappings = new HashSet<EntityMapping>();
- for(String mappingId : resultList){
- EntityMapping entityMapping = getEntityMappingFromRickYard(mappingId);
- if(entityMapping != null){
- mappings.add(entityMapping);
- } else {
- log.info("Unable to getEntityMapping for "+mappingId+" (id was returned as result for a query for EntityMappings -> so that should only happen if the Mapping was deleted in the meantime)");
- }
- }
- return mappings;
- }
- /**
- * Getter for the EntityMapping by ID
- * @param id the ID
- * @return the EntityMapping or <code>null</code> if no Sign is present within the RickYard for the parsed ID
- * @throws IllegalArgumentException if the Sign referenced by the parsed ID is not an valid {@link EntityMapping}.
- */
- protected EntityMapping getEntityMappingFromRickYard(String id) throws IllegalArgumentException,YardException {
- Representation rep = rickYard.getRepresentation(id);
- if(rep != null){
- return new DefaultEntityMappingImpl(config.getRickPrefix(),rep);
- } else {
- return null;
- }
- }
-
- @Override
- public EntityMapping getMappingById(String id) throws RickException{
- return getEntityMappingFromRickYard(id);
- }
- @Override
- public FieldQueryFactory getQueryFavtory() {
- return rickYard.getQueryFactory();
- }
- @Override
- public FieldMapper getFieldMappings() {
- return fieldMapper;
- }
- @Override
- public QueryResultList<Representation> find(FieldQuery query) throws YardException{
- return rickYard.find(query);
- }
- @Override
- public QueryResultList<String> findSymbolReferences(FieldQuery query) throws YardException{
- return rickYard.findReferences(query);
- }
- @Override
- public QueryResultList<Symbol> findSymbols(FieldQuery query) throws YardException{
- QueryResultList<String> references = rickYard.findReferences(query);
- List<Symbol> symbols = new ArrayList<Symbol>(references.size());
- for(String reference : references){
- Symbol symbol = lookupSymbol(reference);
- if(symbol != null){
- symbols.add(symbol);
- } else {
- log.warn("Unable to create Symbol for Reference "+reference+" on RickYard[id="+rickYard.getId()+"] -> ignore reference");
- }
- }
- return new QueryResultListImpl<Symbol>(references.getQuery(), symbols, Symbol.class);
- }
+ private final Logger log = LoggerFactory.getLogger(RickImpl.class);
+
+ /**
+ * The OSGI component context of the Rick
+ */
+ private ComponentContext context;
+ /**
+ * The field mapper holding global mappings that are used for mapping
+ * representations of entities for any referenced sites
+ */
+ protected FieldMapper fieldMapper;
+
+ /**
+ * The yard where this Rick instance stores its data
+ * TODO: this reference is currently initialised in the activate method.
+ * however there are some issues with that.
+ * <ul>
+ * <li> If this Component is activated, before this yard is active, the
+ * activate method throws an Exception and is therefore in the
+ * "unsatisfied" state.
+ * <li> If now the needed Yard is configured this component gets not notified
+ * <li> However defining a Reference is also not possible, because it would
+ * be nice to be able to change the Rick-Yard (e.g. to change the data
+ * set of the Rick at runtime)
+ * <li> I could register a {@link ServiceListener} in the activate method.
+ * But I am not sure if it is allowed to have an active Service Listener
+ * on an component that is in the "unsatisfied" state.
+ * </ul>
+ */
+ protected Yard rickYard; //reference initialised in the activate method
+ /*
+ * TODO: The YardManager is currently not used.
+ */
+ @Reference // 1..1, static
+ protected YardManager yardManager;
+ /**
+ * The Configuration of the Rick
+ * TODO: Maybe refactor this implementation to implement this interface or
+ * to extend the {@link RickConfigurationImpl}.
+ */
+ @Reference // 1..1, static
+ protected RickConfiguration config;
+ /**
+ * The site manager is used to search for entities within the Rick framework
+ */
+ @Reference // 1..1, static
+ protected ReferencedSiteManager siteManager;
+
+ private String DEFAULT_SYMBOL_PREFIX = "symbol";
+ private String DEFAULT_MAPPING_PREFIX = "mapping";
+ /**
+ * Activates the Rick (OSGI Lifecycle method)
+ * @param context the OSGI component context (stored in {@link #context})
+ * @throws ConfigurationException On any error during the activation of
+ * the Rick
+ */
+ @Activate
+ protected void activate(ComponentContext context) throws ConfigurationException {
+ log.info("activating Rick ...");
+ if(context == null){
+ throw new IllegalStateException("Unable to activate if parsed ComponentContext is NULL");
+ } else {
+ this.context = context;
+ }
+ //First check the RICK ID and
+ log.info(" ... init Basic Properties");
+ if(config.getID() == null || config.getID().isEmpty()){
+ throw new ConfigurationException(RickConfiguration.ID, "The Rick Configuration does not define a ID for the Rick");
+ } else {
+ log.info(" + id: "+config.getID());
+ }
+ if(config.getName() == null || config.getName().isEmpty()){
+ throw new ConfigurationException(RickConfiguration.NAME, "The Rick Configuration does not define a name for the Rick");
+ } else {
+ log.info(" + id: "+config.getName());
+ }
+ if(config.getDescription() != null){
+ log.info(" + id: "+config.getDescription());
+ }
+ if(config.getRickPrefix() == null){
+ throw new ConfigurationException(RickConfiguration.PREFIX, "The Rick Configuration does not define a Prefix for the Rick");
+ }
+ try {
+ new URI(config.getRickPrefix());
+ log.info(" + prefix: "+config.getRickPrefix());
+ } catch (URISyntaxException e1) {
+ throw new ConfigurationException(RickConfiguration.PREFIX, "The Prefix configured for the RICK is not an valied URI (prefix="+config.getRickPrefix()+")");
+ }
+ //next get the reference to the configured RickYard
+ log.info(" ... init RickYard");
+// final ServiceReference[] refs;
+// log.info(" - search for services for "+Yard.class+" with Filter "+rickYardFilterString);
+// try {
+// refs = context.getBundleContext().getServiceReferences(
+// Yard.class.getName(),
+// rickYardFilterString);
+//
+// } catch (InvalidSyntaxException e) {
+// throw new ConfigurationException(RickConfiguration.RICK_YARD_ID, "Unable to create Filter for the RickYard based on the parsed vlaue "+config.getRickYardId(),e);
+// }
+// if(refs != null && refs.length>0){
+// log.debug(" - found "+refs.length+" Services");
+// Yard rickYard = null;
+// ServiceReference rickYardReference = null;
+// for(int i=0;i<refs.length && rickYard == null;i++){
+// rickYardReference = refs[i];
+// // I trust the OSGI framework, that the returned service implements the requested Interface
+// rickYard = (Yard)context.getBundleContext().getService(rickYardReference);
+// log.info(" + RickYard "+rickYard.getName()+" (id: "+rickYard.getId()+")");
+// }
+// //configured Yard not present -> unable to activate!
+// if(rickYard == null){
+// throw new ConfigurationException(RickConfiguration.RICK_YARD_ID, "Unable to get Yard Service for the parsed value "+config.getRickYardId());
+// }
+ if(yardManager.isYard(config.getRickYardId())){
+ this.rickYard = yardManager.getYard(config.getRickYardId());
+ String rickYardFilterString = '('+Yard.ID+'='+config.getRickYardId()+')';
+ try {
+ context.getBundleContext().addServiceListener(this,rickYardFilterString);
+ } catch (InvalidSyntaxException e) {
+ log.warn(String.format("Unable to set Filter %s to ServiceListener for RickYard! -> add ServiceListener without Filter",
+ rickYardFilterString),e);
+ context.getBundleContext().addServiceListener(this);
+ }
+ } else {
+ throw new ConfigurationException(RickConfiguration.RICK_YARD_ID, "Unable to get Yard for parsed value "+config.getRickYardId());
+ }
+ //at last get the FieldMappingConfig and create the FieldMappings instance
+ // -> we need to do that after the init of the Rick-yard, because than we
+ // can use the valueFactory of the configured Yard to create instances
+ // of converted values!
+ log.info(" ... init FieldMappings");
+ fieldMapper = new DefaultFieldMapperImpl(ValueConverterFactory.getInstance(rickYard.getValueFactory()));
+ for(String mappingString : config.getFieldMappingConfig()){
+ FieldMapping mapping = FieldMappingUtils.parseFieldMapping(mappingString);
+ if(mapping != null){
+ log.info(" + mapping: "+mapping);
+ fieldMapper.addMapping(mapping);
+ }
+ }
+ }
+ /**
+ * TODO: currently only for debugging. Intended to be used for tracking
+ * the state of dependencies
+ */
+ @Override
+ public void serviceChanged(ServiceEvent event) {
+ log.info("Print Service Event for "+event.getSource());
+ for(String key : event.getServiceReference().getPropertyKeys()){
+ log.info(" > "+key+"="+event.getServiceReference().getProperty(key));
+ }
+ }
+
+ @Deactivate
+ protected void deactivate(ComponentContext context) {
+ log.info("!!deactivate");
+ if(this.rickYard != null){
+ //unregister the serviceListener
+ this.context.getBundleContext().removeServiceListener(this);
+ }
+ this.fieldMapper = null;
+ this.rickYard = null;
+ this.context = null;
+ }
+
+// @Override
+// public RickConfiguration getRickConfiguration() {
+// return config;
+// }
+ @Override
+ public Yard getRickYard() {
+ return rickYard;
+ }
+
+ @Override
+ public Symbol lookupSymbol(String entity) throws YardException{
+ return lookupSymbol(entity,false);
+ }
+
+ @Override
+ public Symbol lookupSymbol(String entity, boolean create) throws YardException {
+ Symbol symbol = getSymbol(entity);
+ if(symbol != null){
+ return symbol;
+ } else {
+ //parsed reference was not a symbol. search for an mapped Entity
+ EntityMapping entityMapping = getMappingByEntity(entity);
+ if(entityMapping != null){
+ symbol = getSymbol(entityMapping.getSymbolId());
+ if(symbol != null){
+ return symbol;
+ } else {
+ log.warn("Unable to find Symbol for Entity Mapping "+entityMapping+"!");
+ return recoverSymbol(entityMapping.getSymbolId());
+ }
+ } else if(create){
+ //search if the parsed reference is known by any referenced site
+ // and if YES, create a new Symbol
+ Sign sign = siteManager.getSign(entity);
+ if(sign == null){ //id not found by any referred site
+ return null;
+ } else {
+ return createSymbol(sign);
+ }
+ } else {
+ return null;
+ }
+ }
+ }
+ @Override
+ public Symbol createSymbol(String reference) throws IllegalStateException, IllegalArgumentException, YardException {
+ Symbol symbol = getSymbol(reference);
+ if(symbol == null){
+ EntityMapping entityMapping = getMappingByEntity(reference);
+ if(entityMapping == null){
+ Sign sign = siteManager.getSign(reference);
+ if(sign == null){
+ return null;
+ } else {
+ return createSymbol(sign);
+ }
+ } else {
+ throw new IllegalStateException("There exists already an EntityMappting for the parsed reference (mapping="+entityMapping+")");
+ }
+ } else {
+ throw new IllegalStateException("The parsed reference is an Symbol (symbol="+symbol+")!");
+ }
+ }
+ /**
+ * Recovers an symbol based on the available {@link EntityMapping}s
+ * @param symbolId the id of the Symbol
+ * @return the Symbol or <code>null</code> if the recovering is unsucessfull.
+ */
+ private Symbol recoverSymbol(String symbolId) {
+ /*
+ * TODO: recover the Symbol by recreating it based on the available
+ * mapped Entities
+ * 1) search for all EntityMappings with this SymbolId
+ * 2) get all mapped Entities
+ * 3) apply the FieldMappings
+ * 4) store the Symbol
+ * 5) return the recovered Symbol
+ */
+ return null;
+ }
+ /*
+ * @throws IllegalArgumentException if a {@link Representation} for the parsed ID is present in the
+ * {@link #rickYard}, but the representation can not be wrapped by an {@link Symbol}.
+ */
+ @Override
+ public Symbol getSymbol(String symbolId) throws IllegalArgumentException,IllegalStateException, YardException {
+ if(symbolId == null || symbolId.isEmpty()){
+ throw new IllegalArgumentException("The parsed symbolID MUST NOT be NULL nor empty!");
+ }
+ Representation rep = rickYard.getRepresentation(symbolId);
+ if(rep != null){
+ try {
+ return new DefaultSymbolImpl(config.getRickPrefix(),rep);
+ } catch(IllegalArgumentException e){
+ String msg = "Unable to create Symbol based on the representation as stored in the Rick";
+ log.warn(msg);
+ if(log.isWarnEnabled()){
+ log.warn(ModelUtils.getRepresentationInfo(rep));
+ }
+ throw new IllegalStateException(msg,e); //re-throw for now
+ }
+ } else {
+ return null;
+ }
+ }
+ protected Symbol createSymbol(Sign sign) throws YardException{
+ if(sign == null){
+ return null;
+ }
+ ReferencedSite signSite = siteManager.getReferencedSite(sign.getSignSite());
+ if(signSite == null){
+ log.warn("Unable to create Symbol because the ReferencedSite "+sign.getSignSite()+" for sign "+sign.getId()+" is currently not active in the RICK -> return null");
+ return null;
+ }
+ Representation symbolRep = rickYard.create(constructResourceId(DEFAULT_SYMBOL_PREFIX));
+ //and set the initial state
+ symbolRep.addReference(Symbol.STATE, config.getDefaultSymbolState().getUri());
+ //create a FieldMapper containing the Rick Mappings and the Site specific mappings
+ //TODO: one could cache such instances
+ FieldMapper siteMapper = signSite.getFieldMapper();
+ FieldMapper mapper = this.fieldMapper.clone();
+ for(FieldMapping siteMapping : siteMapper.getMappings()){
+ mapper.addMapping(siteMapping);
+ }
+ Representation signRep = sign.getRepresentation();
+ //TODO: As soon as MappingActivities are implemented we need to add such
+ // information to the EntityMapping instance!
+ mapper.applyMappings(signRep, symbolRep);
+ //Second create the symbol and init the data
+ Symbol symbol;
+ try {
+ symbol = new DefaultSymbolImpl(config.getRickPrefix(),symbolRep);
+ } catch (IllegalArgumentException e){
+ //unable to create Symbol based on available Information
+ // -> clean up and return null;
+ log.warn("Unable to create Symbol for Representation "+symbolRep.getId()+
+ ", because of missing required fields! -> return null (see more Infos after Stack Trace)",e);
+ if(log.isWarnEnabled()){
+ log.warn(ModelUtils.getRepresentationInfo(symbolRep));
+ }
+ try { //try to remove the created representation in the store
+ rickYard.remove(symbolRep.getId());
+ } catch (YardException e1) {
+ log.warn("Unable to remove Representation "+symbolRep.getId(),e1);
+ }
+ return null;
+ }
+ //Third create and init the mapped Entity
+ EntityMapping entityMapping = new DefaultEntityMappingImpl(
+ config.getRickPrefix(), symbolRep.getId(), signRep.getId(),
+ config.getDefaultMappingState(),
+ rickYard.create(constructResourceId(DEFAULT_MAPPING_PREFIX)));
+ //Store the symbol and the mappedEntity in the rickYard
+ rickYard.store(symbol.getRepresentation());
+ rickYard.store(entityMapping.getRepresentation());
+ return symbol;
+
+ //we need to set the label and the description!
+ }
+ /**
+ * Uses the Prefix as configured by the {@link #config} and the parsed
+ * prefix for the type to create an unique ID for a resource.
+ * @param typePrefix the prefix of the type
+ * @return An id in the form <code> {@link RickConfiguration#getRickPrefix()}
+ * + typePrefix + '.' + {@link ModelUtils#randomUUID()}</code>. Note that between
+ * the rick prefix and the type prefix a separation chars are added
+ * if it is not already defined by the {@link RickConfiguration#getRickPrefix()}
+ * value.
+ */
+ private String constructResourceId(String typePrefix) {
+ StringBuilder id = new StringBuilder();
+ String prefix = config.getRickPrefix();
+ if(prefix == null || prefix.isEmpty()){
+ prefix = Rick.DEFAUTL_RICK_PREFIX;
+ }
+ id.append(prefix);
+ switch(prefix.charAt(prefix.length()-1)){
+ case '#':
+ case ':':
+ break;
+ default: //add a separator
+ if(prefix.startsWith("urn:")){
+ id.append(':'); //use a point for now
+ } else {
+ id.append('/'); //use '/' instead of '#' because one needs not to escape it in GET requests
+ }
+ }
+ if(typePrefix != null && !typePrefix.isEmpty()){
+ id.append(typePrefix);
+ id.append('.');
+ }
+ id.append(ModelUtils.randomUUID());
+ return id.toString();
+ }
+
+
+ @Override
+ public EntityMapping getMappingByEntity(String reference) throws YardException{
+ if(reference == null){
+ log.warn("NULL parsed as Reference -> call to getMappingByEntity ignored (return null)");
+ return null;
+ }
+ FieldQuery fieldQuery = getQueryFavtory().createFieldQuery();
+ fieldQuery.setConstraint(RdfResourceEnum.mappedEntity.getUri(), new ReferenceConstraint(reference));
+ QueryResultList<String> resultList = rickYard.findReferences(fieldQuery);
+ if(!resultList.isEmpty()){
+ Iterator<String> resultIterator = resultList.iterator();
+ EntityMapping entityMapping = getEntityMappingFromRickYard(resultIterator.next());
+ if(resultIterator.hasNext()){
+ log.warn("Multiple Mappings found for Entity "+reference+"!");
+ log.warn(" > "+entityMapping.getId()+" -> returned instance");
+ while(resultIterator.hasNext()){
+ log.warn(" > "+resultIterator.next()+" -> ignored");
+ }
+ }
+ return entityMapping;
+ } else {
+ log.debug("No Mapping found for Entity "+reference);
+ return null;
+ }
+ }
+ @Override
+ public Collection<EntityMapping> getMappingsBySymbol(String symbol) throws YardException{
+ if(symbol == null){
+ log.warn("NULL parsed as Reference -> call to getMappingsBySymbol ignored (return null)");
+ return null;
+ }
+ FieldQuery fieldQuery = getQueryFavtory().createFieldQuery();
+ fieldQuery.setConstraint(RdfResourceEnum.mappedSymbol.getUri(), new ReferenceConstraint(symbol));
+ QueryResultList<String> resultList = rickYard.findReferences(fieldQuery);
+ Collection<EntityMapping> mappings = new HashSet<EntityMapping>();
+ for(String mappingId : resultList){
+ EntityMapping entityMapping = getEntityMappingFromRickYard(mappingId);
+ if(entityMapping != null){
+ mappings.add(entityMapping);
+ } else {
+ log.info("Unable to getEntityMapping for "+mappingId+" (id was returned as result for a query for EntityMappings -> so that should only happen if the Mapping was deleted in the meantime)");
+ }
+ }
+ return mappings;
+ }
+ /**
+ * Getter for the EntityMapping by ID
+ * @param id the ID
+ * @return the EntityMapping or <code>null</code> if no Sign is present within the RickYard for the parsed ID
+ * @throws IllegalArgumentException if the Sign referenced by the parsed ID is not an valid {@link EntityMapping}.
+ */
+ protected EntityMapping getEntityMappingFromRickYard(String id) throws IllegalArgumentException,YardException {
+ Representation rep = rickYard.getRepresentation(id);
+ if(rep != null){
+ return new DefaultEntityMappingImpl(config.getRickPrefix(),rep);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public EntityMapping getMappingById(String id) throws RickException{
+ return getEntityMappingFromRickYard(id);
+ }
+ @Override
+ public FieldQueryFactory getQueryFavtory() {
+ return rickYard.getQueryFactory();
+ }
+ @Override
+ public FieldMapper getFieldMappings() {
+ return fieldMapper;
+ }
+ @Override
+ public QueryResultList<Representation> find(FieldQuery query) throws YardException{
+ return rickYard.find(query);
+ }
+ @Override
+ public QueryResultList<String> findSymbolReferences(FieldQuery query) throws YardException{
+ return rickYard.findReferences(query);
+ }
+ @Override
+ public QueryResultList<Symbol> findSymbols(FieldQuery query) throws YardException{
+ QueryResultList<String> references = rickYard.findReferences(query);
+ List<Symbol> symbols = new ArrayList<Symbol>(references.size());
+ for(String reference : references){
+ Symbol symbol = lookupSymbol(reference);
+ if(symbol != null){
+ symbols.add(symbol);
+ } else {
+ log.warn("Unable to create Symbol for Reference "+reference+" on RickYard[id="+rickYard.getId()+"] -> ignore reference");
+ }
+ }
+ return new QueryResultListImpl<Symbol>(references.getQuery(), symbols, Symbol.class);
+ }
}
Modified: incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/impl/YardManagerImpl.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/impl/YardManagerImpl.java?rev=1044829&r1=1044828&r2=1044829&view=diff
==============================================================================
--- incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/impl/YardManagerImpl.java (original)
+++ incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/impl/YardManagerImpl.java Sun Dec 12 15:02:34 2010
@@ -21,92 +21,92 @@ import eu.iksproject.rick.servicesapi.ya
@Component(immediate = true)
@Service
public class YardManagerImpl implements YardManager {
-
- Logger log = LoggerFactory.getLogger(YardManagerImpl.class);
- @Reference(
- cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
- referenceInterface=Yard.class,
- strategy=ReferenceStrategy.EVENT,
- policy=ReferencePolicy.DYNAMIC,
- bind="bindYard",
- unbind="unbindYard")
- private Map<String,Yard> yards = Collections.emptyMap();
-
-
- @Reference(
- cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
- referenceInterface=Cache.class,
- strategy=ReferenceStrategy.EVENT,
- policy=ReferencePolicy.DYNAMIC,
- bind="bindCache",
- unbind="unbindCache")
- private Map<String,Cache> caches = Collections.emptyMap();// stat with a empty map!
-
-// private ComponentContext context;
-// @Activate
-// protected void activate(ComponentContext context){
-// log.debug("activating "+getClass()+" with "+context);
-// //nothing to do for now!
-// this.context = context;
-// }
-// @Deactivate
-// protected void deactivate(ComponentContext context){
-// context = null;
-// }
- protected void bindYard(Yard yard){
- if(yard != null){
- Map<String, Yard> tmp = new HashMap<String, Yard>(yards);
- tmp.put(yard.getId(),yard);
- this.yards = Collections.unmodifiableMap(tmp);
- }
- }
- protected void unbindYard(Yard yard){
- if(yard != null && yards.containsKey(yard.getId())){
- Map<String, Yard> tmp = new HashMap<String, Yard>(yards);
- tmp.remove(yard.getId());
- this.yards = Collections.unmodifiableMap(tmp);
- }
- }
- protected void bindCache(Cache cache){
- if(cache != null){
- Map<String, Cache> tmp = new HashMap<String, Cache>(caches);
- tmp.put(cache.getId(),cache);
- this.caches = Collections.unmodifiableMap(tmp);
- }
- }
- protected void unbindCache(Cache cache){
- if(cache != null && caches.containsKey(cache.getId())){
- Map<String, Cache> tmp = new HashMap<String, Cache>(caches);
- tmp.remove(cache.getId());
- this.caches = Collections.unmodifiableMap(tmp);
- }
- }
-
- @Override
- public Yard getYard(String id) {
- return yards.get(id);
- }
-
- @Override
- public Collection<String> getYardIDs() {
- return yards.keySet();
- }
-
- @Override
- public boolean isYard(String id) {
- return yards.containsKey(id);
- }
- @Override
- public Cache getCache(String id) {
- Cache cache = caches.get(id);
- return cache;
- }
- @Override
- public Collection<String> getCacheIDs() {
- return caches.keySet();
- }
- @Override
- public boolean isCache(String id) {
- return caches.containsKey(id);
- }
+
+ Logger log = LoggerFactory.getLogger(YardManagerImpl.class);
+ @Reference(
+ cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
+ referenceInterface=Yard.class,
+ strategy=ReferenceStrategy.EVENT,
+ policy=ReferencePolicy.DYNAMIC,
+ bind="bindYard",
+ unbind="unbindYard")
+ private Map<String,Yard> yards = Collections.emptyMap();
+
+
+ @Reference(
+ cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE,
+ referenceInterface=Cache.class,
+ strategy=ReferenceStrategy.EVENT,
+ policy=ReferencePolicy.DYNAMIC,
+ bind="bindCache",
+ unbind="unbindCache")
+ private Map<String,Cache> caches = Collections.emptyMap();// stat with a empty map!
+
+// private ComponentContext context;
+// @Activate
+// protected void activate(ComponentContext context){
+// log.debug("activating "+getClass()+" with "+context);
+// //nothing to do for now!
+// this.context = context;
+// }
+// @Deactivate
+// protected void deactivate(ComponentContext context){
+// context = null;
+// }
+ protected void bindYard(Yard yard){
+ if(yard != null){
+ Map<String, Yard> tmp = new HashMap<String, Yard>(yards);
+ tmp.put(yard.getId(),yard);
+ this.yards = Collections.unmodifiableMap(tmp);
+ }
+ }
+ protected void unbindYard(Yard yard){
+ if(yard != null && yards.containsKey(yard.getId())){
+ Map<String, Yard> tmp = new HashMap<String, Yard>(yards);
+ tmp.remove(yard.getId());
+ this.yards = Collections.unmodifiableMap(tmp);
+ }
+ }
+ protected void bindCache(Cache cache){
+ if(cache != null){
+ Map<String, Cache> tmp = new HashMap<String, Cache>(caches);
+ tmp.put(cache.getId(),cache);
+ this.caches = Collections.unmodifiableMap(tmp);
+ }
+ }
+ protected void unbindCache(Cache cache){
+ if(cache != null && caches.containsKey(cache.getId())){
+ Map<String, Cache> tmp = new HashMap<String, Cache>(caches);
+ tmp.remove(cache.getId());
+ this.caches = Collections.unmodifiableMap(tmp);
+ }
+ }
+
+ @Override
+ public Yard getYard(String id) {
+ return yards.get(id);
+ }
+
+ @Override
+ public Collection<String> getYardIDs() {
+ return yards.keySet();
+ }
+
+ @Override
+ public boolean isYard(String id) {
+ return yards.containsKey(id);
+ }
+ @Override
+ public Cache getCache(String id) {
+ Cache cache = caches.get(id);
+ return cache;
+ }
+ @Override
+ public Collection<String> getCacheIDs() {
+ return caches.keySet();
+ }
+ @Override
+ public boolean isCache(String id) {
+ return caches.containsKey(id);
+ }
}
Modified: incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/mapping/DefaultFieldMapperImpl.java
URL: http://svn.apache.org/viewvc/incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/mapping/DefaultFieldMapperImpl.java?rev=1044829&r1=1044828&r2=1044829&view=diff
==============================================================================
--- incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/mapping/DefaultFieldMapperImpl.java (original)
+++ incubator/stanbol/trunk/rick/generic/core/src/main/java/eu/iksproject/rick/core/mapping/DefaultFieldMapperImpl.java Sun Dec 12 15:02:34 2010
@@ -40,431 +40,431 @@ import eu.iksproject.rick.servicesapi.ut
*
*/
public class DefaultFieldMapperImpl implements FieldMapper {
- private final Logger log = LoggerFactory.getLogger(DefaultFieldMapperImpl.class);
- private final Set<FieldMapping> mappings;
-// private final Map<String,Collection<FieldMapping>> ignoreFieldMap;
-// private final Map<Pattern,Collection<FieldMapping>> ignoreWildcardMap;
- private final Map<String,Set<FieldMapping>> fieldMap;
- private final Map<Pattern,Set<FieldMapping>> wildcardMap;
- private Collection<FieldMapping> unmodMappings;
- ValueConverterFactory valueConverter;
- //private Map<String,FieldMapping> mappings = Collections.synchronizedMap(new HashMap<String, FieldMapping>());
- public DefaultFieldMapperImpl(ValueConverterFactory valueConverter) {
- super();
- mappings = new HashSet<FieldMapping>();
- unmodMappings = Collections.unmodifiableCollection(mappings);
- fieldMap = new HashMap<String, Set<FieldMapping>>();
- wildcardMap = new HashMap<Pattern, Set<FieldMapping>>();
- if(valueConverter == null){
- throw new IllegalArgumentException("The parsed ValueConverterFactory MUST NOT be NULL");
- }
- this.valueConverter = valueConverter;
-// ignoreFieldMap = new HashMap<String, Collection<FieldMapping>>();
-// ignoreWildcardMap = new HashMap<Pattern, Collection<FieldMapping>>();
- }
- /**
- * Internally used by clone
- * @param fieldMap
- * @param wildcardMap
- */
- private DefaultFieldMapperImpl(ValueConverterFactory valueConverter,Set<FieldMapping> mappings,Map<String,Set<FieldMapping>> fieldMap, Map<Pattern,Set<FieldMapping>> 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<FieldMapping> getMappings(String field){
- final List<FieldMapping> mappings = new ArrayList<FieldMapping>();
- //first search the fieldMappings
- Collection<FieldMapping> tmp = fieldMap.get(field);
- if(tmp != null){
- mappings.addAll(tmp);
- }
- //now iterate over the Wildcard Mappings
- for(Entry<Pattern,Set<FieldMapping>> entry : wildcardMap.entrySet()){
- if(entry.getKey().matcher(field).find()){
- mappings.addAll(entry.getValue());
- }
- }
- Collections.sort(mappings, FieldMappingUtils.FIELD_MAPPING_COMPARATOR);
- return mappings;
- }
- /* (non-Javadoc)
- * @see eu.iksproject.rick.servicesapi.mapping.FieldMapper#addMapping(eu.iksproject.rick.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<FieldMapping> fieldPatternMappings = wildcardMap.get(fieldPattern);
- if(fieldPatternMappings == null){
- fieldPatternMappings = new HashSet<FieldMapping>();//new TreeSet<FieldMapping>(FieldMappingUtils.FIELD_MAPPING_COMPARATOR);
- wildcardMap.put(fieldPattern, fieldPatternMappings);
- }
- fieldPatternMappings.add(mapping);
- }
- } else {
- String fieldName = mapping.getFieldPattern();
- synchronized (fieldMap) {
- Set<FieldMapping> fieldPatternMappings = fieldMap.get(fieldName);
- if(fieldPatternMappings == null){
- fieldPatternMappings = new HashSet<FieldMapping>();//new TreeSet<FieldMapping>(FieldMappingUtils.FIELD_MAPPING_COMPARATOR);
- fieldMap.put(fieldName, fieldPatternMappings);
- }
- fieldPatternMappings.add(mapping);
- }
- }
- } //else already present -> nothing todo
- }
- public Collection<FieldMapping> getMappings(){
- return unmodMappings;
- }
-// private static String getPrefix(String fieldPattern){
-// return fieldPattern.split("[\\?\\*]")[0];
-// }
- /* (non-Javadoc)
- * @see eu.iksproject.rick.servicesapi.mapping.FieldMapper#removeFieldMapping(eu.iksproject.rick.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<FieldMapping> 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<FieldMapping> 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 eu.iksproject.rick.servicesapi.mapping.FieldMapper#applyMappings(eu.iksproject.rick.servicesapi.model.Representation, eu.iksproject.rick.servicesapi.model.Representation)
- */
- public Representation applyMappings(Representation source, Representation target) {
- Collection<String> fields = new HashSet<String>();
- for(Iterator<String> fieldIt = source.getFieldNames();fieldIt.hasNext();){
- fields.add(fieldIt.next());
- }
- for(String field : fields){
-// log.info(" > process field: "+field);
- //get the active Mappings
- List<FieldMapping> activeMappings = getMappings(field);
- if(!activeMappings.isEmpty()){
- //get all the values (store them in an Collection, because we need them more than once)
- Collection<Object> values = new ArrayList<Object>();
- for(Iterator<Object> valueIt = source.get(field);valueIt.hasNext();){
- values.add(valueIt.next());
- }
- //only to be sure, that this is not changed by Filters!
- values = Collections.unmodifiableCollection(values);
- /*
- * (1) Before working with the values first analyse the active
- * mappings and filters. Two things
- * a) Init Wildcard Filters:
- * Language filters set on namespaces are executed on all field
- * mappings that define no language filter
- * b) calculate the mapped fields. Possible there are no mappings
- * left. Than we need not to process all the values
- */
- Set<String> targetFields = new HashSet<String>();
- TextConstraint globalFilter = null;
- Collection<Object> globalFiltered = null;
- /*
- * NOTE: the mappings are sorted in the way, that the most
- * prominent one will be at index 0. The wildcard "*" will
- * be always the last.
- * So we need to parse backwards because than more prominent
- * things will overwrite and win!
- */
- for(int i=activeMappings.size()-1;i>=0;i--){
- FieldMapping mapping = activeMappings.get(i);
- if(mapping.usesWildcard() //if wildcard
- && !mapping.ignoreField() && //and not ignore
- mapping.getFilter() != null && //and a filter is present
- mapping.getFilter().getType() == ConstraintType.text){ //and of type text
- //set the global text filter.
- //NOTE: the active mappings are sorted in that way, that
- // the most specific one is set last
- globalFilter = (TextConstraint)mapping.getFilter();
- }
- for(String targetField : mapping.getMappings()){
- if(mapping.ignoreField()){
- targetFields.remove(targetField);
- } else {
- targetFields.add(targetField);
- }
- }
- }
-// log.info(" o targets: "+targetFields);
-// log.info(" o global text filter: "+globalFilter);
- if(globalFilter != null){
- globalFiltered = new HashSet<Object>(values);
- //parse false ass third argument, because we need not to filter
- //non-Text values for wildcard filter!
- processFilter(globalFilter, globalFiltered,false);
- }
- //now process the mappings
- for(FieldMapping mapping : activeMappings){
- if(!mapping.ignoreField() &&
- !Collections.disjoint(targetFields, mapping.getMappings())){
- processMapping(mapping, field, values,globalFiltered, targetFields, target);
-// } else if(!mapping.ignoreField()) {
-// log.info(String.format(" << ignore mapping %s ",mapping));
-// } else {
-// log.info(String.format(" << %s ",mapping));
- }
- }
- }
- }
- /*
- * TODO: return a "MappingReport"
- * All mapping activities should be documented and stored with the
- * MappedEntity as MappingActivity!
- */
- return target;
- }
- /**
- *
- * @param mapping
- * @param field
- * @param values
- * @param globalFiltered
- * @param targets
- */
- private void processMapping(FieldMapping mapping, String field, Collection<Object> values, Collection<Object> globalFiltered, Set<String> activeTargets,Representation targetRepresentation) {
- //parsed mappings are all !ignore and some mappings are active
- Collection<Object> filtered; //this collection will be modified by the filters later on
- if(globalFiltered == null || //if no global filter is present and therefore globalFiltered == null or
- //there is a more special text filter defined in this mapping
- mapping.getFilter() != null && mapping.getFilter().getType() == ConstraintType.text){
- filtered = new HashSet<Object>(values);//start with all values
- } else { //start with the values filtered by the global filter
- filtered = new HashSet<Object>(globalFiltered);
- }
- if(mapping.getFilter()!=null){
- switch (mapping.getFilter().getType()) {
- case value:
- ValueConstraint valueConstraint = (ValueConstraint)mapping.getFilter();
- processFilter(valueConstraint,filtered);
- break;
- case text:
- TextConstraint textConstraint = (TextConstraint)mapping.getFilter();
- //for wildcard mappings only filter TextValues. if the mapping is
- //for a specific field filter also non text values.
- processFilter(textConstraint,filtered,!mapping.usesWildcard());
- break;
- default:
- log.warn(String.format("Filter of type %s are not supported -> select all values! (Constraint=%s)",
- mapping.getFilter().getType(),mapping.getFilter()));
- break;
- }
- /*
- * TODO: add general purpose functionality to apply Constraints.
- * Currently this is done by the specific Query Implementations :(
- * - use the constraint to filter the values collection!
- */
-
- } //nothing to do
- for(String mappedField : mapping.getMappings()){
- //activeTargets still uses null for the current field
- // -> this is because wildcard filters can not know the actual field name
- if(activeTargets.contains(mappedField)){ //so use null to match
- if(mappedField == null){ //and than replace null with the field name
- mappedField = field;
- }
-// log.info(String.format(" >> copy%s to %s &d values",
-// mappedField.equals(field)?"":" from "+field,mappedField,filtered.size()));
- targetRepresentation.add(mappedField, filtered);
-// } else {
-// log.info(String.format(" << ignore%s %s",
-// mappedField.equals(field)?"":"mapping from "+field+"to",mappedField));
- }
- }
+ private final Logger log = LoggerFactory.getLogger(DefaultFieldMapperImpl.class);
+ private final Set<FieldMapping> mappings;
+// private final Map<String,Collection<FieldMapping>> ignoreFieldMap;
+// private final Map<Pattern,Collection<FieldMapping>> ignoreWildcardMap;
+ private final Map<String,Set<FieldMapping>> fieldMap;
+ private final Map<Pattern,Set<FieldMapping>> wildcardMap;
+ private Collection<FieldMapping> unmodMappings;
+ ValueConverterFactory valueConverter;
+ //private Map<String,FieldMapping> mappings = Collections.synchronizedMap(new HashMap<String, FieldMapping>());
+ public DefaultFieldMapperImpl(ValueConverterFactory valueConverter) {
+ super();
+ mappings = new HashSet<FieldMapping>();
+ unmodMappings = Collections.unmodifiableCollection(mappings);
+ fieldMap = new HashMap<String, Set<FieldMapping>>();
+ wildcardMap = new HashMap<Pattern, Set<FieldMapping>>();
+ if(valueConverter == null){
+ throw new IllegalArgumentException("The parsed ValueConverterFactory MUST NOT be NULL");
+ }
+ this.valueConverter = valueConverter;
+// ignoreFieldMap = new HashMap<String, Collection<FieldMapping>>();
+// ignoreWildcardMap = new HashMap<Pattern, Collection<FieldMapping>>();
+ }
+ /**
+ * Internally used by clone
+ * @param fieldMap
+ * @param wildcardMap
+ */
+ private DefaultFieldMapperImpl(ValueConverterFactory valueConverter,Set<FieldMapping> mappings,Map<String,Set<FieldMapping>> fieldMap, Map<Pattern,Set<FieldMapping>> 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<FieldMapping> getMappings(String field){
+ final List<FieldMapping> mappings = new ArrayList<FieldMapping>();
+ //first search the fieldMappings
+ Collection<FieldMapping> tmp = fieldMap.get(field);
+ if(tmp != null){
+ mappings.addAll(tmp);
+ }
+ //now iterate over the Wildcard Mappings
+ for(Entry<Pattern,Set<FieldMapping>> entry : wildcardMap.entrySet()){
+ if(entry.getKey().matcher(field).find()){
+ mappings.addAll(entry.getValue());
+ }
+ }
+ Collections.sort(mappings, FieldMappingUtils.FIELD_MAPPING_COMPARATOR);
+ return mappings;
+ }
+ /* (non-Javadoc)
+ * @see eu.iksproject.rick.servicesapi.mapping.FieldMapper#addMapping(eu.iksproject.rick.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<FieldMapping> fieldPatternMappings = wildcardMap.get(fieldPattern);
+ if(fieldPatternMappings == null){
+ fieldPatternMappings = new HashSet<FieldMapping>();//new TreeSet<FieldMapping>(FieldMappingUtils.FIELD_MAPPING_COMPARATOR);
+ wildcardMap.put(fieldPattern, fieldPatternMappings);
+ }
+ fieldPatternMappings.add(mapping);
+ }
+ } else {
+ String fieldName = mapping.getFieldPattern();
+ synchronized (fieldMap) {
+ Set<FieldMapping> fieldPatternMappings = fieldMap.get(fieldName);
+ if(fieldPatternMappings == null){
+ fieldPatternMappings = new HashSet<FieldMapping>();//new TreeSet<FieldMapping>(FieldMappingUtils.FIELD_MAPPING_COMPARATOR);
+ fieldMap.put(fieldName, fieldPatternMappings);
+ }
+ fieldPatternMappings.add(mapping);
+ }
+ }
+ } //else already present -> nothing todo
+ }
+ public Collection<FieldMapping> getMappings(){
+ return unmodMappings;
+ }
+// private static String getPrefix(String fieldPattern){
+// return fieldPattern.split("[\\?\\*]")[0];
+// }
+ /* (non-Javadoc)
+ * @see eu.iksproject.rick.servicesapi.mapping.FieldMapper#removeFieldMapping(eu.iksproject.rick.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<FieldMapping> 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<FieldMapping> 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 eu.iksproject.rick.servicesapi.mapping.FieldMapper#applyMappings(eu.iksproject.rick.servicesapi.model.Representation, eu.iksproject.rick.servicesapi.model.Representation)
+ */
+ public Representation applyMappings(Representation source, Representation target) {
+ Collection<String> fields = new HashSet<String>();
+ for(Iterator<String> fieldIt = source.getFieldNames();fieldIt.hasNext();){
+ fields.add(fieldIt.next());
+ }
+ for(String field : fields){
+// log.info(" > process field: "+field);
+ //get the active Mappings
+ List<FieldMapping> activeMappings = getMappings(field);
+ if(!activeMappings.isEmpty()){
+ //get all the values (store them in an Collection, because we need them more than once)
+ Collection<Object> values = new ArrayList<Object>();
+ for(Iterator<Object> valueIt = source.get(field);valueIt.hasNext();){
+ values.add(valueIt.next());
+ }
+ //only to be sure, that this is not changed by Filters!
+ values = Collections.unmodifiableCollection(values);
+ /*
+ * (1) Before working with the values first analyse the active
+ * mappings and filters. Two things
+ * a) Init Wildcard Filters:
+ * Language filters set on namespaces are executed on all field
+ * mappings that define no language filter
+ * b) calculate the mapped fields. Possible there are no mappings
+ * left. Than we need not to process all the values
+ */
+ Set<String> targetFields = new HashSet<String>();
+ TextConstraint globalFilter = null;
+ Collection<Object> globalFiltered = null;
+ /*
+ * NOTE: the mappings are sorted in the way, that the most
+ * prominent one will be at index 0. The wildcard "*" will
+ * be always the last.
+ * So we need to parse backwards because than more prominent
+ * things will overwrite and win!
+ */
+ for(int i=activeMappings.size()-1;i>=0;i--){
+ FieldMapping mapping = activeMappings.get(i);
+ if(mapping.usesWildcard() //if wildcard
+ && !mapping.ignoreField() && //and not ignore
+ mapping.getFilter() != null && //and a filter is present
+ mapping.getFilter().getType() == ConstraintType.text){ //and of type text
+ //set the global text filter.
+ //NOTE: the active mappings are sorted in that way, that
+ // the most specific one is set last
+ globalFilter = (TextConstraint)mapping.getFilter();
+ }
+ for(String targetField : mapping.getMappings()){
+ if(mapping.ignoreField()){
+ targetFields.remove(targetField);
+ } else {
+ targetFields.add(targetField);
+ }
+ }
+ }
+// log.info(" o targets: "+targetFields);
+// log.info(" o global text filter: "+globalFilter);
+ if(globalFilter != null){
+ globalFiltered = new HashSet<Object>(values);
+ //parse false ass third argument, because we need not to filter
+ //non-Text values for wildcard filter!
+ processFilter(globalFilter, globalFiltered,false);
+ }
+ //now process the mappings
+ for(FieldMapping mapping : activeMappings){
+ if(!mapping.ignoreField() &&
+ !Collections.disjoint(targetFields, mapping.getMappings())){
+ processMapping(mapping, field, values,globalFiltered, targetFields, target);
+// } else if(!mapping.ignoreField()) {
+// log.info(String.format(" << ignore mapping %s ",mapping));
+// } else {
+// log.info(String.format(" << %s ",mapping));
+ }
+ }
+ }
+ }
+ /*
+ * TODO: return a "MappingReport"
+ * All mapping activities should be documented and stored with the
+ * MappedEntity as MappingActivity!
+ */
+ return target;
+ }
+ /**
+ *
+ * @param mapping
+ * @param field
+ * @param values
+ * @param globalFiltered
+ * @param targets
+ */
+ private void processMapping(FieldMapping mapping, String field, Collection<Object> values, Collection<Object> globalFiltered, Set<String> activeTargets,Representation targetRepresentation) {
+ //parsed mappings are all !ignore and some mappings are active
+ Collection<Object> filtered; //this collection will be modified by the filters later on
+ if(globalFiltered == null || //if no global filter is present and therefore globalFiltered == null or
+ //there is a more special text filter defined in this mapping
+ mapping.getFilter() != null && mapping.getFilter().getType() == ConstraintType.text){
+ filtered = new HashSet<Object>(values);//start with all values
+ } else { //start with the values filtered by the global filter
+ filtered = new HashSet<Object>(globalFiltered);
+ }
+ if(mapping.getFilter()!=null){
+ switch (mapping.getFilter().getType()) {
+ case value:
+ ValueConstraint valueConstraint = (ValueConstraint)mapping.getFilter();
+ processFilter(valueConstraint,filtered);
+ break;
+ case text:
+ TextConstraint textConstraint = (TextConstraint)mapping.getFilter();
+ //for wildcard mappings only filter TextValues. if the mapping is
+ //for a specific field filter also non text values.
+ processFilter(textConstraint,filtered,!mapping.usesWildcard());
+ break;
+ default:
+ log.warn(String.format("Filter of type %s are not supported -> select all values! (Constraint=%s)",
+ mapping.getFilter().getType(),mapping.getFilter()));
+ break;
+ }
+ /*
+ * TODO: add general purpose functionality to apply Constraints.
+ * Currently this is done by the specific Query Implementations :(
+ * - use the constraint to filter the values collection!
+ */
- }
- /**
- * This method filters the parsed {@link Text} values based on the languages
- * parsed in the {@link TextConstraint}.
- * This method modifies the parsed collection by using the
- * {@link Iterator#remove()} method.
- * @param textConstraint the text constraint containing the active languages
- * @param values the values to filter. This method modifies this collection
- * @return the modified collection to allow nested calls
- */
- private Collection<Object> processFilter(TextConstraint textConstraint, Collection<Object> values,boolean filterNonTextValues) {
- if(textConstraint.getText() != null){
- log.warn("Filtering based on values is not implemented");
- }
- /*
- * TODO: If filterNonTextValues=true and acceptDefaultLanguate=true
- * we could also try to convert non-Text values to Text (by using
- * the valueConverter.
- */
- Set<String> langs = textConstraint.getLanguages();
- boolean acceptDefaultLanguage = textConstraint.getLanguages().contains(null);
- for(Iterator<Object> it = values.iterator();it.hasNext();){
- Object value = it.next();
- if(value instanceof Text){
- if(!langs.contains(((Text)value).getLanguage())){
- it.remove();
-// log.info(String.format(" - value %s(type:%s) rejected by text filter",value,value.getClass()));
-// } else {
-// log.info(String.format(" + value %s(type:%s) accepted by text filter",value,value.getClass()));
- }
- } else if(filterNonTextValues && value instanceof String){
- //Strings only if the default language is enabled
- if(!acceptDefaultLanguage){
- it.remove();
-// log.info(String.format(" - value %s(type:%s) rejected by text filter",value,value.getClass()));
-// } else {
-// log.info(String.format(" + value %s(type:%s) accepted by text filter",value,value.getClass()));
- }
- } else if(filterNonTextValues){
- it.remove();
-// log.info(String.format(" - value %s(type:%s) rejected by text filter",value,value.getClass()));
- } //else non text value and filterNonTextValues=false -> nothing to do
- }
- return values;
- }
- /**
- * This method converts - or if not possible filters the parsed values based
- * on the parsed constraint
- * @param valueConstraint
- * @param values
- * @return
- */
- private Collection<Object> processFilter(ValueConstraint valueConstraint, Collection<Object> values) {
- if(valueConstraint.getValue() != null){
- log.warn("Filtering based on values is not yet implemented");
- }
- //1) collect all active dataTypes
- //first a EnumSet for really fast containsAll ... operations
- Set<DataTypeEnum> activeDataTypes = EnumSet.noneOf(DataTypeEnum.class);
- //second a List to keep track of the ordering of the dataTypes in the
- //constraint for later conversions!
- List<DataTypeEnum> sortedActiveDataTypes = new ArrayList<DataTypeEnum>(valueConstraint.getDataTypes().size());
- //NOTE: using a LinkedHashSet would slow down this code, because EnumSet
- // gives constant processing time even for bulk operations!
- for(String dataTypeUri : valueConstraint.getDataTypes()){
- DataTypeEnum dataType = DataTypeEnum.getDataType(dataTypeUri);
- if(dataType == null){
- log.warn(String.format("DataType %s not supported"));
- } else {
- if(activeDataTypes.add(dataType)){
- //only of set has changed to avoid duplicates in the list
- sortedActiveDataTypes.add(dataType);
- }
- }
- }
- //2) now process the values
-// log.info(" --- Filter values ---");
- //calculating acceptable and not acceptable types needs some processing time
- //and usually values will be only of very less different types.
- //Therefore it makes sense to cache accepted and rejected types!
- Set<Class<?>> accepted = new HashSet<Class<?>>();
- Set<Class<?>> rejected = new HashSet<Class<?>>();
- //Set that stores rejected values. Such will be converted later on!
- Set<Object> needConversion = new HashSet<Object>();
- for(Iterator<Object> it = values.iterator();it.hasNext();){
- Object value = it.next();
- if(accepted.contains(value.getClass())){
-// log.info(String.format(" + value %s(type:%s) accepted by value filter",value,value.getClass()));
- //nothing to do
- } else if(rejected.contains(value.getClass())){
- it.remove(); //remove also the current value of that type
- needConversion.add(value); //save as value that need to be converted
-// log.info(String.format(" - value %s(type:%s) rejected by value filter",value,value.getClass()));
- } else { //new class ... calculate
- Set<DataTypeEnum> valueTypes = DataTypeEnum.getAllDataTypes(value.getClass());
- if(valueTypes.removeAll(activeDataTypes)){
- accepted.add(value.getClass());
-// log.info(String.format(" + value %s(type:%s) accepted by value filter",value,value.getClass()));
- } else {
- rejected.add(getClass());
- it.remove(); //remove the Item
- needConversion.add(value); //save as value that need to be converted
-// log.info(String.format(" - value %s(type:%s) rejected by value filter",value,value.getClass()));
- }
- }
- }
- //3) try to convert values to the active dataTypes
-// log.info(" --- Try to Convert rejected values ---");
- for(Object value : needConversion){
- Object converted = null;
- DataTypeEnum convertedTo = null;
- for(Iterator<DataTypeEnum> dataTypes = sortedActiveDataTypes.iterator(); //iterate over all active dataTypes
- converted == null && dataTypes.hasNext();){ //while converted still null and more dataTypes to try
- convertedTo = dataTypes.next();
- converted = valueConverter.convert(value, convertedTo.getUri()); //try the conversion
- }
- if(converted != null){
-// log.info(String.format(" + value %s(javaType=%s) successfully converted to %s(datatype=%s)",
-// value,value.getClass().getSimpleName(),converted,convertedTo.getShortName()));
- values.add(converted);
-// } else {
-// log.info(String.format(" - value %s(javaType=%s) could not be converted"),
-// value,value.getClass().getSimpleName());
- }
- }
- return values;
- }
- @Override
- public DefaultFieldMapperImpl clone() {
- return new DefaultFieldMapperImpl(this.valueConverter,this.mappings,this.fieldMap, this.wildcardMap);
- }
- @Override
- public int hashCode() {
- return mappings.hashCode();
- }
- @Override
- public boolean equals(Object o) {
- return o != null && o instanceof DefaultFieldMapperImpl &&
- ((DefaultFieldMapperImpl)o).mappings.equals(mappings);
- }
+ } //nothing to do
+ for(String mappedField : mapping.getMappings()){
+ //activeTargets still uses null for the current field
+ // -> this is because wildcard filters can not know the actual field name
+ if(activeTargets.contains(mappedField)){ //so use null to match
+ if(mappedField == null){ //and than replace null with the field name
+ mappedField = field;
+ }
+// log.info(String.format(" >> copy%s to %s &d values",
+// mappedField.equals(field)?"":" from "+field,mappedField,filtered.size()));
+ targetRepresentation.add(mappedField, filtered);
+// } else {
+// log.info(String.format(" << ignore%s %s",
+// mappedField.equals(field)?"":"mapping from "+field+"to",mappedField));
+ }
+ }
+
+ }
+ /**
+ * This method filters the parsed {@link Text} values based on the languages
+ * parsed in the {@link TextConstraint}.
+ * This method modifies the parsed collection by using the
+ * {@link Iterator#remove()} method.
+ * @param textConstraint the text constraint containing the active languages
+ * @param values the values to filter. This method modifies this collection
+ * @return the modified collection to allow nested calls
+ */
+ private Collection<Object> processFilter(TextConstraint textConstraint, Collection<Object> values,boolean filterNonTextValues) {
+ if(textConstraint.getText() != null){
+ log.warn("Filtering based on values is not implemented");
+ }
+ /*
+ * TODO: If filterNonTextValues=true and acceptDefaultLanguate=true
+ * we could also try to convert non-Text values to Text (by using
+ * the valueConverter.
+ */
+ Set<String> langs = textConstraint.getLanguages();
+ boolean acceptDefaultLanguage = textConstraint.getLanguages().contains(null);
+ for(Iterator<Object> it = values.iterator();it.hasNext();){
+ Object value = it.next();
+ if(value instanceof Text){
+ if(!langs.contains(((Text)value).getLanguage())){
+ it.remove();
+// log.info(String.format(" - value %s(type:%s) rejected by text filter",value,value.getClass()));
+// } else {
+// log.info(String.format(" + value %s(type:%s) accepted by text filter",value,value.getClass()));
+ }
+ } else if(filterNonTextValues && value instanceof String){
+ //Strings only if the default language is enabled
+ if(!acceptDefaultLanguage){
+ it.remove();
+// log.info(String.format(" - value %s(type:%s) rejected by text filter",value,value.getClass()));
+// } else {
+// log.info(String.format(" + value %s(type:%s) accepted by text filter",value,value.getClass()));
+ }
+ } else if(filterNonTextValues){
+ it.remove();
+// log.info(String.format(" - value %s(type:%s) rejected by text filter",value,value.getClass()));
+ } //else non text value and filterNonTextValues=false -> nothing to do
+ }
+ return values;
+ }
+ /**
+ * This method converts - or if not possible filters the parsed values based
+ * on the parsed constraint
+ * @param valueConstraint
+ * @param values
+ * @return
+ */
+ private Collection<Object> processFilter(ValueConstraint valueConstraint, Collection<Object> values) {
+ if(valueConstraint.getValue() != null){
+ log.warn("Filtering based on values is not yet implemented");
+ }
+ //1) collect all active dataTypes
+ //first a EnumSet for really fast containsAll ... operations
+ Set<DataTypeEnum> activeDataTypes = EnumSet.noneOf(DataTypeEnum.class);
+ //second a List to keep track of the ordering of the dataTypes in the
+ //constraint for later conversions!
+ List<DataTypeEnum> sortedActiveDataTypes = new ArrayList<DataTypeEnum>(valueConstraint.getDataTypes().size());
+ //NOTE: using a LinkedHashSet would slow down this code, because EnumSet
+ // gives constant processing time even for bulk operations!
+ for(String dataTypeUri : valueConstraint.getDataTypes()){
+ DataTypeEnum dataType = DataTypeEnum.getDataType(dataTypeUri);
+ if(dataType == null){
+ log.warn(String.format("DataType %s not supported"));
+ } else {
+ if(activeDataTypes.add(dataType)){
+ //only of set has changed to avoid duplicates in the list
+ sortedActiveDataTypes.add(dataType);
+ }
+ }
+ }
+ //2) now process the values
+// log.info(" --- Filter values ---");
+ //calculating acceptable and not acceptable types needs some processing time
+ //and usually values will be only of very less different types.
+ //Therefore it makes sense to cache accepted and rejected types!
+ Set<Class<?>> accepted = new HashSet<Class<?>>();
+ Set<Class<?>> rejected = new HashSet<Class<?>>();
+ //Set that stores rejected values. Such will be converted later on!
+ Set<Object> needConversion = new HashSet<Object>();
+ for(Iterator<Object> it = values.iterator();it.hasNext();){
+ Object value = it.next();
+ if(accepted.contains(value.getClass())){
+// log.info(String.format(" + value %s(type:%s) accepted by value filter",value,value.getClass()));
+ //nothing to do
+ } else if(rejected.contains(value.getClass())){
+ it.remove(); //remove also the current value of that type
+ needConversion.add(value); //save as value that need to be converted
+// log.info(String.format(" - value %s(type:%s) rejected by value filter",value,value.getClass()));
+ } else { //new class ... calculate
+ Set<DataTypeEnum> valueTypes = DataTypeEnum.getAllDataTypes(value.getClass());
+ if(valueTypes.removeAll(activeDataTypes)){
+ accepted.add(value.getClass());
+// log.info(String.format(" + value %s(type:%s) accepted by value filter",value,value.getClass()));
+ } else {
+ rejected.add(getClass());
+ it.remove(); //remove the Item
+ needConversion.add(value); //save as value that need to be converted
+// log.info(String.format(" - value %s(type:%s) rejected by value filter",value,value.getClass()));
+ }
+ }
+ }
+ //3) try to convert values to the active dataTypes
+// log.info(" --- Try to Convert rejected values ---");
+ for(Object value : needConversion){
+ Object converted = null;
+ DataTypeEnum convertedTo = null;
+ for(Iterator<DataTypeEnum> dataTypes = sortedActiveDataTypes.iterator(); //iterate over all active dataTypes
+ converted == null && dataTypes.hasNext();){ //while converted still null and more dataTypes to try
+ convertedTo = dataTypes.next();
+ converted = valueConverter.convert(value, convertedTo.getUri()); //try the conversion
+ }
+ if(converted != null){
+// log.info(String.format(" + value %s(javaType=%s) successfully converted to %s(datatype=%s)",
+// value,value.getClass().getSimpleName(),converted,convertedTo.getShortName()));
+ values.add(converted);
+// } else {
+// log.info(String.format(" - value %s(javaType=%s) could not be converted"),
+// value,value.getClass().getSimpleName());
+ }
+ }
+ return values;
+ }
+ @Override
+ public DefaultFieldMapperImpl clone() {
+ return new DefaultFieldMapperImpl(this.valueConverter,this.mappings,this.fieldMap, this.wildcardMap);
+ }
+ @Override
+ public int hashCode() {
+ return mappings.hashCode();
+ }
+ @Override
+ public boolean equals(Object o) {
+ return o != null && o instanceof DefaultFieldMapperImpl &&
+ ((DefaultFieldMapperImpl)o).mappings.equals(mappings);
+ }
}