/**
*
*/
package org.ihtsdo.otf.refset.graph.gao;
import static org.ihtsdo.otf.refset.domain.RGC.EFFECTIVE_DATE;
import static org.ihtsdo.otf.refset.domain.RGC.ID;
import static org.ihtsdo.otf.refset.domain.RGC.PUBLISHED;
import static org.ihtsdo.otf.refset.domain.RGC.REFERENCE_COMPONENT_ID;
import static org.ihtsdo.otf.refset.domain.RGC.TYPE;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.ihtsdo.otf.refset.domain.Member;
import org.ihtsdo.otf.refset.domain.Refset;
import org.ihtsdo.otf.refset.exception.EntityNotFoundException;
import org.ihtsdo.otf.refset.graph.RefsetGraphAccessException;
import org.ihtsdo.otf.refset.graph.RefsetGraphFactory;
import org.ihtsdo.otf.refset.graph.schema.GRefset;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;
import org.springframework.util.StringUtils;
import com.thinkaurelius.titan.core.TitanGraph;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.FramedGraphFactory;
import com.tinkerpop.gremlin.java.GremlinPipeline;
/**Graph Access component to retrieve {@link Refset}s and its {@link Member}
* for export.
*/
@Repository
public class RefsetExportGAO {
private static final Logger LOGGER = LoggerFactory.getLogger(RefsetExportGAO.class);
private RefsetGraphFactory rgFactory;//refset graph factory
private static FramedGraphFactory fgf = new FramedGraphFactory();
/**Retrieves a {@link Refset} for a given refsetId
* @param id
* @return {@link Refset}
* @throws RefsetGraphAccessException
*/
public Refset getRefset(String id) throws RefsetGraphAccessException, EntityNotFoundException {
LOGGER.debug("Geting member data for export for given refset id {} ", id);
TitanGraph g = null;
Refset r = null;
try {
g = rgFactory.getReadOnlyGraph();
Iterable<Vertex> vRs = g.query().has(ID, id).has(TYPE, VertexType.refset.toString()).vertices();
if(!vRs.iterator().hasNext()) {
throw new EntityNotFoundException("No Refset available for given refset id");
}
Vertex vR = vRs.iterator().next();
r = RefsetConvertor.getRefset(fgf.create(g).frame(vR, GRefset.class));
r.setMembers(new ArrayList<Member>());
/*export required all member which are not published yet*/
GremlinPipeline<Vertex, Vertex> pipe = new GremlinPipeline<Vertex, Vertex>(g);
pipe.start(vR).inE(EdgeLabel.members.toString()).outV()
.has(PUBLISHED, 0)
.has(TYPE, VertexType.member.toString());
List<Vertex> vMs = pipe.toList();
for (Vertex vM : vMs) {
//check effective time. To be eligible for export Member effective time greater than > latest effective time or empty
Object et = vM.getProperty(EFFECTIVE_DATE);
if(!(et == null || new DateTime(et).isAfter(r.getLatestEffectiveTime()))) {
LOGGER.debug("Not eligible for export due to effectivetime threshold : {} ", et, vM.getId());
continue;
}
Iterable<Edge> edges = vM.getEdges(Direction.OUT, EdgeLabel.members.toString());
for (Edge edge : edges) {
if ( edge.getPropertyKeys().contains(REFERENCE_COMPONENT_ID) ) {
Member m = RefsetConvertor.getMember(vM);
String referenceComponentId = edge.getProperty(REFERENCE_COMPONENT_ID);
m.setReferencedComponentId(referenceComponentId);
LOGGER.debug("Adding current state of member & its detail {} ", m);
r.getMembers().add(m);
//check if this member also has a history state.
GremlinPipeline<Vertex, Vertex> mPipe = new GremlinPipeline<Vertex, Vertex>(g);
mPipe.start(vM).outE(EdgeLabel.hasState.toString()).inV().has(TYPE, VertexType.hMember.toString()).has(PUBLISHED, 1).range(0, 1);
Iterable<Vertex> vHms = mPipe.toList();
for (Vertex vHm : vHms) {
Member hm = RefsetConvertor.getMember(vHm);
Member merged = merge(hm, m);
LOGGER.debug("Adding historical state of member & its detail {} ", merged);
if (!r.getMembers().contains(merged)) {
r.getMembers().add(merged);
break;
}
}
}
}
}
RefsetGraphFactory.commit(g);
} catch(EntityNotFoundException e) {
RefsetGraphFactory.rollback(g);
LOGGER.error("entity not found for given refset id {}", id, e);
throw e;
} catch (Exception e) {
RefsetGraphFactory.rollback(g);
LOGGER.error("Error getting refset for", id, e);
throw new RefsetGraphAccessException(e.getMessage(), e);
} finally {
RefsetGraphFactory.shutdown(g);
}
return r;
}
/**
* @param hm
* @param m
*/
private Member merge(Member hm, Member m) {
if(StringUtils.isEmpty(hm.getModuleId())) {
hm.setModuleId(m.getModuleId());
}
if(StringUtils.isEmpty(hm.getReferencedComponentId())) {
hm.setReferencedComponentId(m.getReferencedComponentId());
}
return hm;
}
/**
* @param factory the factory to set
*/
@Resource(name = "refsetGraphFactory")
public void setRGFactory(RefsetGraphFactory factory) {
this.rgFactory = factory;
}
}