/**
* Copyright 2014 IHTSDO
* Licensed 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.ihtsdo.otf.refset.graph.gao;
import static org.ihtsdo.otf.refset.domain.RGC.*;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.ihtsdo.otf.refset.graph.RefsetGraphFactory;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.thinkaurelius.titan.core.TitanGraph;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener;
/**
*Listener to Member node events capture and create corresponding state nodes
*/
public class Rf2ImportMemberChangeListener implements GraphChangedListener {
private static final Logger LOGGER = LoggerFactory.getLogger(Rf2ImportMemberChangeListener.class);
//these will be the ids of history member vertices per transaction where key is current vertex id
//and value is corresponding history vertex id
private Map<Object, Object> historyVertexIds = new ConcurrentHashMap<Object, Object>();
//these will be the ids of history member edge per transaction where key is history vertex id
//and value is corresponding edge id
private Map<Object, Object> historyEdgeIds = new ConcurrentHashMap<Object, Object>();
private final TitanGraph g;
private final String user;
public Rf2ImportMemberChangeListener(final TitanGraph g, final String user) {
this.g = g;
this.user = user;
}
/* (non-Javadoc)
* @see com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener#vertexAdded(com.tinkerpop.blueprints.Vertex)
*/
@Override
public void vertexAdded(Vertex vertex) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener#vertexPropertyChanged(com.tinkerpop.blueprints.Vertex, java.lang.String, java.lang.Object, java.lang.Object)
*/
@Override
public void vertexPropertyChanged(Vertex cV, String key,
Object oldValue, Object setValue) {
Object type = cV.getProperty(TYPE);
if (!VertexType.member.toString().equals(type)) {
return;
}
try {
if (!(oldValue != null && oldValue.equals(setValue)
|| setValue != null && setValue.equals(oldValue)
|| setValue == oldValue) && oldValue != null) {
createHistoryMemberNode(cV.getId());
LOGGER.debug("Adding old {} value - {} to history refset vertex", key, oldValue);
Vertex hV = g.getVertex(historyVertexIds.get(cV.getId()));
hV.setProperty(key, oldValue);
//add relation if does not exist already
addStateRelation(hV, cV);
RefsetGraphFactory.commit(g);
}
} catch (Exception e) {
LOGGER.debug("Error during change state capture", e);
RefsetGraphFactory.rollback(g);
}
}
/**
* Adds history vertex up front so that any change in current refset can be added to this history refset.
* one per transaction there will be only on history refset. hence few meta property should be added upfront.
*
*/
private void createHistoryMemberNode(Object currentVertexId) {
if (!historyVertexIds.containsKey(currentVertexId)) {
LOGGER.debug("Adding history vertex");
final Vertex v = g.addVertexWithLabel(g.getVertexLabel("GMember"));
v.setProperty(TYPE, VertexType.hMember.toString());
v.setProperty(CREATED, new DateTime().getMillis());
v.setProperty(CREATED_BY, user);
historyVertexIds.put(currentVertexId, v.getId());
LOGGER.debug("History vertex with an id - {} was added by {}", v.getId(), user);
} else {
LOGGER.debug("Not adding history vertex as it already exist with an id - {}", historyVertexIds.get(currentVertexId), user);
}
}
/* (non-Javadoc)
* @see com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener#vertexPropertyRemoved(com.tinkerpop.blueprints.Vertex, java.lang.String, java.lang.Object)
*/
@Override
public void vertexPropertyRemoved(Vertex cV, String key,
Object removedValue) {
}
/**
* @param hV
* @param cV
*/
private void addStateRelation(Vertex hV, Vertex cV) {
if (!historyEdgeIds.containsKey(hV.getId())) {
//also update sid if available to history refset.
hV.setProperty(ID, cV.getProperty(ID));
Edge e = cV.addEdge(EdgeLabel.hasState.toString(), hV);
historyEdgeIds.put(hV.getId(), e.getId());
e.setProperty(START, cV.getProperty(MODIFIED_DATE));
e.setProperty(END, new DateTime().getMillis());
LOGGER.debug("State edge with an id - {} was added by {}", e.getId(), user);
} else {
LOGGER.debug("Not adding state edge as it already exist with an id - {}", historyEdgeIds.get(hV.getId()), user);
}
}
/* (non-Javadoc)
* @see com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener#vertexRemoved(com.tinkerpop.blueprints.Vertex, java.util.Map)
*/
@Override
public void vertexRemoved(Vertex vertex, Map<String, Object> props) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener#edgeAdded(com.tinkerpop.blueprints.Edge)
*/
@Override
public void edgeAdded(Edge edge) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener#edgePropertyChanged(com.tinkerpop.blueprints.Edge, java.lang.String, java.lang.Object, java.lang.Object)
*/
@Override
public void edgePropertyChanged(Edge edge, String key, Object oldValue,
Object setValue) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener#edgePropertyRemoved(com.tinkerpop.blueprints.Edge, java.lang.String, java.lang.Object)
*/
@Override
public void edgePropertyRemoved(Edge edge, String key, Object removedValue) {
// TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see com.tinkerpop.blueprints.util.wrappers.event.listener.GraphChangedListener#edgeRemoved(com.tinkerpop.blueprints.Edge, java.util.Map)
*/
@Override
public void edgeRemoved(Edge edge, Map<String, Object> props) {
// TODO Auto-generated method stub
}
}