/*
* This is eMonocot, a global online biodiversity information resource.
*
* Copyright © 2011–2015 The Board of Trustees of the Royal Botanic Gardens, Kew and The University of Oxford
*
* eMonocot is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* eMonocot is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* The complete text of the GNU Affero General Public License is in the source repository as the file
* ‘COPYING’. It is also available from <http://www.gnu.org/licenses/>.
*/
package org.emonocot.job.dwc.read;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.emonocot.api.Service;
import org.emonocot.model.Annotation;
import org.emonocot.model.BaseData;
import org.emonocot.model.NonOwned;
import org.emonocot.model.Taxon;
import org.emonocot.model.constants.AnnotationCode;
import org.emonocot.model.constants.AnnotationType;
import org.emonocot.model.constants.RecordType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.ChunkListener;
/**
*
* @author ben
*
*/
public abstract class NonOwnedProcessor<T extends BaseData, SERVICE extends Service<T>> extends DarwinCoreProcessor<T> implements
ChunkListener {
/**
*
*/
private Logger logger = LoggerFactory.getLogger(NonOwnedProcessor.class);
/**
*
*/
protected Map<String, T> boundObjects = new HashMap<String, T>();
/**
*
*/
protected SERVICE service;
/**
* @param t an object
* @throws Exception if something goes wrong
* @return T an object
*/
public final T doProcess(final T t)
throws Exception {
logger.info("Validating " + t.getIdentifier());
if(doFilter(t)) {
return null;
}
Taxon taxon = null;
if(!((NonOwned)t).getTaxa().isEmpty()) {
taxon = super.getTaxonService().find(((NonOwned)t).getTaxa().iterator().next().getIdentifier());
((NonOwned)t).getTaxa().clear();
((NonOwned)t).getTaxa().add(taxon);
super.checkTaxon(getRecordType(), t, ((NonOwned)t).getTaxa().iterator().next());
}
//TODO Simplify this lookup (abstract away whether it is retrieved from chuck of 'bound items' or DB)
T bound = lookupBound(t);
if (bound == null) {
T persisted = null;
if(t.getIdentifier() != null) {
persisted = retrieveBound(t);
} else {
t.setIdentifier(UUID.randomUUID().toString());
}
if (persisted == null) {
doPersist(t);
validate(t);
bind(t);
t.setAuthority(getSource());
Annotation annotation = createAnnotation(t, getRecordType(), AnnotationCode.Create, AnnotationType.Info);
t.getAnnotations().add(annotation);
logger.info("Adding object " + t.getIdentifier());
return t;
} else {
checkAuthority(getRecordType(), t, persisted.getAuthority());
// We've seen this object before, but not in this chunk
if (skipUnmodified && ((persisted.getModified() != null && t.getModified() != null)
&& !persisted.getModified().isBefore(t.getModified()))) {
// Assume the object hasn't changed, but maybe this taxon
// should be associated with it
replaceAnnotation(persisted, AnnotationType.Info, AnnotationCode.Skipped);
if(taxon != null) {
if (((NonOwned)persisted).getTaxa().contains(taxon)) {
// do nothing
} else {
// Add the taxon to the list of taxa
bind(persisted);
logger.info("Updating object " + t.getIdentifier());
((NonOwned)persisted).getTaxa().add(taxon);
}
}
return persisted;
} else {
// Assume that this is the first of several times this object
// appears in the result set, and we'll use this version to
// overwrite the existing object
persisted.setAccessRights(t.getAccessRights());
persisted.setCreated(t.getCreated());
persisted.setLicense(t.getLicense());
persisted.setModified(t.getModified());
persisted.setRights(t.getRights());
persisted.setRightsHolder(t.getRightsHolder());
doUpdate(persisted, t);
((NonOwned)persisted).getTaxa().clear();
if(taxon != null) {
((NonOwned)persisted).getTaxa().add(taxon);
}
validate(t);
bind(persisted);
replaceAnnotation(persisted, AnnotationType.Info, AnnotationCode.Update);
logger.info("Overwriting object " + t.getIdentifier());
return persisted;
}
}
} else {
// We've already seen this object within this chunk and we'll
// update it with this taxon but that's it, assuming that it
// isn't a more up to date version
if(taxon != null) {
if (((NonOwned)bound).getTaxa().contains(taxon)) {
// do nothing
} else {
// Add the taxon to the list of taxa
((NonOwned)bound).getTaxa().add(taxon);
}
}
// We've already returned this object once
logger.info("Skipping object " + t.getIdentifier());
return null;
}
}
protected abstract boolean doFilter(T t);
protected abstract void doUpdate(T persisted, T t);
protected abstract void doPersist(T t);
protected abstract RecordType getRecordType();
protected abstract void bind(T t);
protected abstract T retrieveBound(T t);
protected abstract T lookupBound(T t);
protected abstract void doValidate(T t) throws Exception;
public void afterChunk() {
super.afterChunk();
logger.info("After Chunk");
}
public void beforeChunk() {
super.beforeChunk();
logger.info("Before Chunk");
boundObjects = new HashMap<String, T>();
}
}