Author: ernst
Date: 2009-07-01 22:52:13 +0200 (Wed, 01 Jul 2009)
New Revision: 36516
Modified:
speeltuin/ernst/mmbase-republisher/src/main/java/nl/vpro/mmbase/republisher/RepublisherEventListener.java
speeltuin/ernst/mmbase-republisher/src/test/java/nl/vpro/mmbase/republisher/RepublisherEventListenerTest.java
Log:
work in progress
Modified:
speeltuin/ernst/mmbase-republisher/src/main/java/nl/vpro/mmbase/republisher/RepublisherEventListener.java
===================================================================
---
speeltuin/ernst/mmbase-republisher/src/main/java/nl/vpro/mmbase/republisher/RepublisherEventListener.java
2009-07-01 20:42:49 UTC (rev 36515)
+++
speeltuin/ernst/mmbase-republisher/src/main/java/nl/vpro/mmbase/republisher/RepublisherEventListener.java
2009-07-01 20:52:13 UTC (rev 36516)
@@ -14,6 +14,7 @@
import org.mmbase.bridge.*;
import org.mmbase.bridge.util.Queries;
import org.mmbase.core.event.*;
+import org.mmbase.storage.search.Step;
import org.mmbase.util.logging.Logger;
import org.mmbase.util.logging.Logging;
@@ -102,9 +103,12 @@
} else if (event.getType() == RelationEvent.TYPE_CHANGE) {
handleRelationUpdate(event);
}
-
}
+ /**
+ * When a node is created and the node type can be mapped to a root
entity: try to publish it.:
+ * @param event
+ */
private void handleNodeCreate(NodeEvent event) {
Object entity = findEntity(event.getBuilderName(),
event.getNodeNumber());
if (entity != null) {
@@ -116,24 +120,64 @@
}
}
+ /**
+ * <pre>
+ * TODO:The question is: can we still do all the stuff we do with updated
nodes: is the node still there or is it
+ * already deleted. if so: the event is quite useless, and we can not do
a thing.
+ * I am for now assuming that the node is still there, and we can check if
the document was valid, so published.
+ *
+ * and:
+ * with node deletes the situation can arise that a document was valid,
has been published, and now is no longer valid.
+ * in this case it should be republished with modification type 'delete'.
the practical implication is that 'tryToPublish' should inverse it's
+ * workings: an entity will be published when it is NOT valid.
+ * The question is: how can we assert that the entity was both valid
before the node delete and invalid after:
+ * When the event is handled two things are possible:
+ *
+ * - the 'deleted' node is still there, and we can check if the document
is/was valid with this node.
+ * - the 'deleted' node is not there anymore, and we could check if the
entity is still valid, if we can find the entity (which is hard when the node
is gone).
+ *
+ * What to do: discuss this, and find a reasonable yet simple behavior for
deleted nodes.
+ * </pre>
+ *
+ * @param event
+ */
private void handleNodeDelete(NodeEvent event) {
- // TODO Auto-generated method stub
+ handleNodeChange(event, ModificationType.DELETE);
}
+
private void handleNodeUpdate(NodeEvent event) {
+ handleNodeChange(event, ModificationType.UPDATE);
+ }
+
+ /**
+ * <pre>
+ * The following possibilities should be considered:
+ * - the node can be mapped to a root entity: try to publish that entity
+ * - the node can be mapped to a non-root entity: find all aggregating
root entities, and publish those
+ * - the node can not be mapped to an entity, but nodes of this type can
be embedded by on or more entities: for each such possibility:
+ * -find the embedding entity:
+ * - is it a root entity: try to publish it
+ * - is it a non-root entity: find all aggregating root entities,
and publish those
+ * </pre>
+ * @param event the node event
+ * @param modificationType the type of document modification (could be
resolved from node event)
+ */
+ private void handleNodeChange(NodeEvent event, ModificationType
modificationType) {
+// if(event.getType()= = NodeEvent.TYPE_CHANGE)
Object entity = findEntity(event.getBuilderName(),
event.getNodeNumber());
if(entity != null){
if(EntityConfigLoader.entityIsRoot(entity)){
- tryToPublishDocument(entity, ModificationType.UPDATE);
+ tryToPublishDocument(entity, modificationType);
}else{
- tryToPublishRootEntities(cloud.getNode(event.getNodeNumber()),
entity, ModificationType.UPDATE);
+ tryToPublishRootEntities(cloud.getNode(event.getNodeNumber()),
entity.getClass(), modificationType);
}
}else{
for(EmbeddingEntity embeddingEntity:
findEmbeddingEntities(event)){
if(EntityConfigLoader.entityIsRoot(embeddingEntity.entity)){
- tryToPublishDocument(embeddingEntity.entity,
ModificationType.UPDATE);
+ tryToPublishDocument(embeddingEntity.entity,
modificationType);
}else{
- tryToPublishRootEntities(embeddingEntity.entityNode,
embeddingEntity.entity, ModificationType.UPDATE);
+ tryToPublishRootEntities(embeddingEntity.entityNode,
embeddingEntity.entity.getClass(), modificationType);
}
}
}
@@ -142,21 +186,21 @@
/**
* @param node event
- * @return a list of entities that embed this event's node. These are not
just possible embeddings, but loaded entities that are related to the given
node.
+ * @return a list of entities that embed this event's node. These are not
just possible embeddings,
+ * but loaded entities that are related to the given node.
*/
private List<EmbeddingEntity> findEmbeddingEntities(NodeEvent event) {
- List<EntityEmbedding> embeddingsFor =
entityConfigLoader.findEntitiesThatEmbed(event.getBuilderName());
Node node = cloud.getNode(event.getNodeNumber());
List<EmbeddingEntity> embeddingEntities = new
ArrayList<EmbeddingEntity>();
- //find the entities that really embedding this node.
//we invert the query directory, because we run the query backwards
(from the embedded node to the embedding node)
- for(EntityEmbedding embedding: embeddingsFor){
+ for(EntityEmbedding embedding:
entityConfigLoader.findEntitiesThatEmbed(event.getBuilderName())){
NodeList nl = node.getRelatedNodes(
cloud.getNodeManager(embedding.embeddingType),
embedding.relationRole,
inverseDirection(embedding.queryDirection).toString());
-
+
+ //it's not likely but possible more than one node is embedding the
event's node.
for(NodeIterator ni = nl.nodeIterator(); ni.hasNext();){
Node entityNode = ni.nextNode();
String managerName = entityNode.getNodeManager().getName();
@@ -177,37 +221,39 @@
}
/**
- * find all the root entities that aggregate this entity, or that
aggregate entities that aggregate this entity.
- * Try to publish each in the ordinary way.
- * @param nodenr the node that represents the given entity
- * @param entity
+ * find all the root entities that aggregate this entity, directly or
indirectly.
+ * The root entities are found by first finding all the possible paths to
root entities, and then query all these to find the actual existing nodes.
+ * Then for all found root entity nodes entity instances are created and
publication is attempted in the ordinary way.
+ * @param node the node that represents the aggregated entity
+ * @param entity the aggregated entity
*/
-
- private void tryToPublishRootEntities( Node node, Object entity,
ModificationType modificationType) {
- //find all possible mapped paths to root entities
- List<Path> possibleRootEntityPaths =
entityConfigLoader.findPathsToAggregatingEntities(entity.getClass()) ;
+ private void tryToPublishRootEntities( Node node, Class<?> entityClass,
ModificationType modificationType) {
+ List<Path> possibleRootEntityPaths =
entityConfigLoader.findPathsToAggregatingEntities(entityClass) ;
List<Node> rootEntities = new ArrayList<Node>();
for(Path path : possibleRootEntityPaths){
- rootEntities.addAll(findNodesForActualRootEntities(node, path));
+ rootEntities.addAll(findRootEntityNodes(node, path));
}
for(Node rootNode: rootEntities){
- Object rootEntity = populator.unmarshallNode(rootNode,
node.getNodeManager().getName());
+ Object rootEntity = populator.unmarshallNode(rootNode,
rootNode.getNodeManager().getName());
tryToPublishDocument(rootEntity, modificationType);
}
}
/**
- * Finds nodes that represent root entities that are actually connected to
a given node
+ * Finds nodes that represent root entities that are actually connected to
a given entity node.
* the type of the returned nodes is always equal to the root field of the
given path.
- * @param nodenr
- * @param path
- * @return
+ * @param node
+ * @param path a query path from 'a' root entity to the entity this node
represents
+ * @return a list of nodes of the root entity type that are actually
connected to this node through the path
*/
- private List<Node> findNodesForActualRootEntities(Node node, Path path) {
+ private List<Node> findRootEntityNodes(Node node, Path path) {
List<Node>rootNodes = new ArrayList<Node>();
Query query =cloud.createQuery();
- Queries.addPath(query, path.pathAsString(),
path.queryDirectionsAsString());
+ List<Step>steps = Queries.addPath(query, path.pathAsString(),
path.queryDirectionsAsString());
+ //TODO:test if this is the proper way to add the constraint on the
node.
+ steps.get(steps.size() - 1).addNode(node.getNumber());
+
for(NodeIterator ni = cloud.getList(query).nodeIterator();
ni.hasNext();){
rootNodes.add(ni.nextNode().getNodeValue(path.root));
}
@@ -223,9 +269,63 @@
}
private void handleRelationUpdate(RelationEvent event) {
+ int relSrc = event.getRelationSourceNumber();
+ int relDest = event.getRelationDestinationNumber();
+ String role = getRole(event.getRole());
+
+ if (entityExistsFor(nodeManager(relSrc)) ||
entityExistsFor(nodeManager(relDest))) {
+ if (isEntityThatAggregates(relSrc, relDest, role) ||
isEntityThatEmbeds(relSrc, relDest, role)) {
+ Object entity =
populator.unmarshallNode(cloud.getNode(relSrc), nodeManager(relSrc));
+ if(EntityConfigLoader.entityIsRoot(entity)){
+ //publish entity
+ }else{
+ //find root entities and publish those
+ }
+ } else if (isEntityThatAggregates(relDest, relSrc, role) ||
isEntityThatEmbeds(relDest, relSrc, role)) {
+ Object entity =
populator.unmarshallNode(cloud.getNode(relDest), nodeManager(relDest));
+ if(EntityConfigLoader.entityIsRoot(entity)){
+ //publish entity
+ }else{
+ //find root entities and publish those
+ }
+ }
+ }
+ }
+
+ private boolean isEntityThatAggregates(int sourceNode, int destNode,
String role) {
+ if(entityExistsFor(nodeManager(sourceNode)) &&
entityExistsFor(nodeManager(destNode))){
+ return entityAggregates(entityClass(sourceNode),
entityClass(destNode), role);
+ }
+ return false;
+ }
+
+ private boolean entityAggregates(Object entityClass, Object entityClass2,
String role) {
// TODO Auto-generated method stub
+ return false;
}
+
+ private Object entityClass(int sourceNode) {
+ return
entityConfigLoader.getEntityRegistry().get(nodeManager(sourceNode));
+ }
+
+ private boolean isEntityThatEmbeds(int entityNode, int embeddedNode,
String role) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ private String getRole(int role) {
+ return cloud.getNode(role).getStringValue("sname");
+ }
+
+
+ private String nodeManager(int nodenr){
+ return cloud.getNode(nodenr).getNodeManager().getName();
+ }
+ private boolean entityExistsFor(String nodeManager){
+ return entityConfigLoader.getEntityRegistry().get(nodeManager) !=
null;
+ }
+
/**
* Publish the entity when:
* - the validator validates it.
Modified:
speeltuin/ernst/mmbase-republisher/src/test/java/nl/vpro/mmbase/republisher/RepublisherEventListenerTest.java
===================================================================
---
speeltuin/ernst/mmbase-republisher/src/test/java/nl/vpro/mmbase/republisher/RepublisherEventListenerTest.java
2009-07-01 20:42:49 UTC (rev 36515)
+++
speeltuin/ernst/mmbase-republisher/src/test/java/nl/vpro/mmbase/republisher/RepublisherEventListenerTest.java
2009-07-01 20:52:13 UTC (rev 36516)
@@ -32,6 +32,7 @@
*
*/
public class RepublisherEventListenerTest {
+ private static final String SERIALIZED_DOCUMENT = "serialized document";
private Populator populator;
private RepublisherEventListener eventListener;
private DocumentValidator validator;
@@ -54,7 +55,7 @@
expect(validator.isValid(anyObject())).andReturn(true).atLeastOnce();
serializer = createMock(DocumentSerializer.class);
-
expect(serializer.serializeDocument(anyObject())).andReturn("serialized
document").atLeastOnce();
+
expect(serializer.serializeDocument(anyObject())).andReturn(SERIALIZED_DOCUMENT).atLeastOnce();
cloud= createMock(Cloud.class);
@@ -98,7 +99,7 @@
//check
assertNotNull(endPoint.getDocumentModification());
assertEquals(ModificationType.CREATE,
endPoint.getDocumentModification().getType());
- assertEquals("serialized document",
endPoint.getDocumentModification().getSerializedDocument());
+ assertEquals(SERIALIZED_DOCUMENT,
endPoint.getDocumentModification().getSerializedDocument());
}
/**
@@ -125,11 +126,22 @@
/**
- * updated node events that map to a root entity should republish this
entity when it is valid
+ * updated node events that map to a root entity should republish this
entity when valid
*/
@Test
public void TestUpdateNodeEventOnRootEntity(){
-
+ //setup
+ NodeEvent event = createNodeEvent("news", 1234, NodeEvent.TYPE_CHANGE);
+
expect(cloud.getNode(1234)).andReturn(queryHelper.getNews()).atLeastOnce();
+ replay(cloud);
+
+ assertEquals("test news",cloud.getNode(1234).getStringValue("title"));
+
+ //do it
+ eventListener.notify(event);
+
+ //check
+ assertEquals(SERIALIZED_DOCUMENT,
endPoint.getDocumentModification().getSerializedDocument());
}
/**
@@ -138,6 +150,17 @@
*/
@Test
public void TestUpdateNodeEventOnNonrootEntity(){
+ NodeEvent event = createNodeEvent("news", 1234, NodeEvent.TYPE_CHANGE);
+
expect(cloud.getNode(1234)).andReturn(queryHelper.getNews()).atLeastOnce();
+ replay(cloud);
+
+ assertEquals("test news",cloud.getNode(1234).getStringValue("title"));
+
+ //do it
+ eventListener.notify(event);
+
+ //check
+ assertEquals(SERIALIZED_DOCUMENT,
endPoint.getDocumentModification().getSerializedDocument());
}
_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs