Author: ernst
Date: 2009-06-29 16:36:10 +0200 (Mon, 29 Jun 2009)
New Revision: 36473
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/RepublisherModule.java
speeltuin/ernst/mmbase-republisher/src/test/java/nl/vpro/mmbase/republisher/MyNewsDummyTest.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-06-29 14:36:06 UTC (rev 36472)
+++
speeltuin/ernst/mmbase-republisher/src/main/java/nl/vpro/mmbase/republisher/RepublisherEventListener.java
2009-06-29 14:36:10 UTC (rev 36473)
@@ -1,14 +1,21 @@
package nl.vpro.mmbase.republisher;
+import java.util.ArrayList;
+import java.util.List;
+
import nl.vpro.mmbase.republisher.endpoint.*;
import nl.vpro.mmbase.republisher.serializer.DocumentSerializer;
import nl.vpro.mmbase.republisher.validator.DocumentValidator;
-import nl.vpro.mmbase.vob.Populator;
+import nl.vpro.mmbase.vob.*;
+import nl.vpro.mmbase.vob.EntityConfigLoader.EntityEmbedding;
+import nl.vpro.mmbase.vob.EntityConfigLoader.Path;
import org.apache.commons.lang.SerializationException;
-import org.mmbase.bridge.Cloud;
-import org.mmbase.bridge.Node;
+import org.mmbase.bridge.*;
+import org.mmbase.bridge.util.Queries;
import org.mmbase.core.event.*;
+import org.mmbase.util.logging.Logger;
+import org.mmbase.util.logging.Logging;
public final class RepublisherEventListener implements NodeEventListener,
RelationEventListener {
private Populator populator;
@@ -17,6 +24,8 @@
private DocumentValidator documentValidator;
private CloudProvider cloudProvider;
private Cloud cloud;
+ private EntityConfigLoader entityConfigLoader;
+ private static final Logger log =
Logging.getLoggerInstance(RepublisherEventListener.class);
@@ -32,6 +41,7 @@
public void init() {
if (publicationEndPoint != null) {
publicationEndPoint.init();
+ cloud = getCloud();
}
}
@@ -63,6 +73,7 @@
public void setPopulator(Populator populator) {
this.populator = populator;
+ this.entityConfigLoader = populator.getEntityConfigLoader();
}
DocumentValidator getDocumentValidator() {
@@ -95,40 +106,114 @@
}
private void handleNodeCreate(NodeEvent event) {
- if (populator.hasEntityFor(event.getBuilderName())) {
- Node node = getCloud().getNode(event.getNodeNumber());
- Object entity = populator.unmarshallNode(node,
event.getBuilderName());
- if(Populator.entityIsRoot(entity)){
- if (documentValidator.isValid(entity)) {
- tryToPublishDocument(entity, ModificationType.CREATE);
+ Object entity = findEntity(event.getBuilderName(),
event.getNodeNumber());
+ if (entity != null) {
+ if (EntityConfigLoader.entityIsRoot(entity)) {
+ tryToPublishDocument(entity, ModificationType.CREATE);
}else{
- //..
+ //do nothing. only root entities need to be published
}
}
+ }
+
+ private void handleNodeDelete(NodeEvent event) {
+ // TODO Auto-generated method stub
+ }
+
+ private void handleNodeUpdate(NodeEvent event) {
+ Object entity = findEntity(event.getBuilderName(),
event.getNodeNumber());
+ if(entity != null){
+ if(EntityConfigLoader.entityIsRoot(entity)){
+ tryToPublishDocument(entity, ModificationType.UPDATE);
+ }else{
+ tryToPublishRootEntities(cloud.getNode(event.getNodeNumber()),
entity, ModificationType.UPDATE);
+ }
+ }else{
+ for(EmbeddingEntity embeddingEntity:
findEmbeddingEntities(event)){
+
if(EntityConfigLoader.entityIsRoot(embeddingEntity.entity)){
+ tryToPublishDocument(embeddingEntity.entity,
ModificationType.UPDATE);
+ }else{
+ tryToPublishRootEntities(embeddingEntity.entityNode,
embeddingEntity.entity, ModificationType.UPDATE);
+ }
+ }
}
}
- private void tryToPublishDocument(Object entity, ModificationType
modificationType) {
- try{
- if(documentValidator.isValid(entity)){
- String document = documentSerializer.serializeDocument(entity);
- publicationEndPoint.publishDocument(new
DocumentModification(modificationType, document));
+
+ /**
+ * @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.
+ */
+ 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){
+ NodeList nl = node.getRelatedNodes(
+ cloud.getNodeManager(embedding.embeddingType),
+ embedding.relationRole,
+ inverseDirection(embedding.queryDirection).toString());
+
+ for(NodeIterator ni = nl.nodeIterator(); ni.hasNext();){
+ Node entityNode = ni.nextNode();
+ String managerName = entityNode.getNodeManager().getName();
+ embeddingEntities.add(new EmbeddingEntity(entityNode,
populator.unmarshallNode(entityNode, managerName)));
}
- }catch(SerializationException se){
- //...
- }catch(PublicationException pe){
- //..
}
+ return embeddingEntities;
}
- private void handleNodeDelete(NodeEvent event) {
- // TODO Auto-generated method stub
+ private QueryDirection inverseDirection(QueryDirection queryDirection) {
+ if(queryDirection == QueryDirection.SOURCE){
+ return QueryDirection.DESTINATION;
+ }else if(queryDirection == QueryDirection.DESTINATION){
+ return QueryDirection.SOURCE;
+ }else{
+ return QueryDirection.BOTH;
+ }
}
- private void handleNodeUpdate(NodeEvent event) {
- // TODO Auto-generated method stub
+ /**
+ * 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
+ */
+
+ private void tryToPublishRootEntities( Node node, Object entity,
ModificationType modificationType) {
+ //find all possible mapped paths to root entities
+ List<Path> possibleRootEntityPaths =
entityConfigLoader.findPathsToAggregatingEntities(entity.getClass()) ;
+ List<Node> rootEntities = new ArrayList<Node>();
+ for(Path path : possibleRootEntityPaths){
+ rootEntities.addAll(findNodesForActualRootEntities(node, path));
+ }
+
+ for(Node rootNode: rootEntities){
+ Object rootEntity = populator.unmarshallNode(rootNode,
node.getNodeManager().getName());
+ tryToPublishDocument(rootEntity, modificationType);
+ }
}
+ /**
+ * Finds nodes that represent root entities that are actually connected to
a given node
+ * the type of the returned nodes is always equal to the root field of the
given path.
+ * @param nodenr
+ * @param path
+ * @return
+ */
+ private List<Node> findNodesForActualRootEntities(Node node, Path path) {
+ List<Node>rootNodes = new ArrayList<Node>();
+ Query query =cloud.createQuery();
+ Queries.addPath(query, path.pathAsString(),
path.queryDirectionsAsString());
+ for(NodeIterator ni = cloud.getList(query).nodeIterator();
ni.hasNext();){
+ rootNodes.add(ni.nextNode().getNodeValue(path.root));
+ }
+ return rootNodes;
+ }
+
private void handleRelationCreate(RelationEvent event) {
// TODO Auto-generated method stub
}
@@ -141,11 +226,65 @@
// TODO Auto-generated method stub
}
+ /**
+ * Publish the entity when:
+ * - the validator validates it.
+ * - it can be serialized without problems
+ * - it can be handled by the publication endpoint without problems.
+ * @param entity
+ * @param modificationType
+ * @throws SerializationException, PublicationException
+ */
+ private void tryToPublishDocument(Object entity, ModificationType
modificationType) {
+ try{
+ if(documentValidator.isValid(entity)){
+ String document = documentSerializer.serializeDocument(entity);
+ publicationEndPoint.publishDocument(new
DocumentModification(modificationType, document));
+ }else{
+ log.debug(String.format("Entityt %s is not a valid document
and wil not be published",entity));
+ }
+ }catch(SerializationException se){
+ //...
+ }catch(PublicationException pe){
+ //..
+ }
+ }
+
+ /**
+ * TODO: if the node is embedded, it is not an entity, but it is part of
one.
+ * how to deal with that? how to create the entity:
+ * - find the path to the embedding entity
+ * - query the node
+ * - get the entity for that node
+ *
+ * @param nodeType
+ * @param nodeNr
+ * @return
+ */
+ private Object findEntity(String nodeType, int nodeNr){
+ if (entityConfigLoader.hasEntityFor(nodeType)) {
+ Node node = getCloud().getNode(nodeNr);
+ return populator.unmarshallNode(node, nodeType);
+ }else{
+ log.debug(String.format("no entity found for node type %s",
nodeType));
+ }
+ return null;
+ }
+
private Cloud getCloud(){
if(cloud == null){
cloud = cloudProvider.getCloud();
}
return cloud;
}
+
+ static final class EmbeddingEntity{
+ final Node entityNode;
+ final Object entity;
+ public EmbeddingEntity(Node entityNode, Object entity) {
+ this.entityNode = entityNode;
+ this.entity = entity;
+ }
+ }
}
Modified:
speeltuin/ernst/mmbase-republisher/src/main/java/nl/vpro/mmbase/republisher/RepublisherModule.java
===================================================================
---
speeltuin/ernst/mmbase-republisher/src/main/java/nl/vpro/mmbase/republisher/RepublisherModule.java
2009-06-29 14:36:06 UTC (rev 36472)
+++
speeltuin/ernst/mmbase-republisher/src/main/java/nl/vpro/mmbase/republisher/RepublisherModule.java
2009-06-29 14:36:10 UTC (rev 36473)
@@ -2,6 +2,7 @@
import nl.vpro.mmbase.republisher.endpoint.DummyPublicationEndPoint;
import nl.vpro.mmbase.republisher.serializer.ToStringSerializer;
+import nl.vpro.mmbase.vob.EntityConfigLoader;
import nl.vpro.mmbase.vob.Populator;
import org.apache.commons.lang.StringUtils;
@@ -47,7 +48,7 @@
republisher.setPublicationEndPoint(new DummyPublicationEndPoint());
republisher.setCloudProvider(new AuthorizedCloudProvider(username,
password));
republisher.init();
- republisher.setPopulator(new Populator(pathToScan));
+ republisher.setPopulator(new Populator(new
EntityConfigLoader(pathToScan)));
return republisher;
}
Modified:
speeltuin/ernst/mmbase-republisher/src/test/java/nl/vpro/mmbase/republisher/MyNewsDummyTest.java
===================================================================
---
speeltuin/ernst/mmbase-republisher/src/test/java/nl/vpro/mmbase/republisher/MyNewsDummyTest.java
2009-06-29 14:36:06 UTC (rev 36472)
+++
speeltuin/ernst/mmbase-republisher/src/test/java/nl/vpro/mmbase/republisher/MyNewsDummyTest.java
2009-06-29 14:36:10 UTC (rev 36473)
@@ -53,7 +53,8 @@
@Test
public void testPopulatorWithMyNewsDummy(){
MyNewsDummy queryHelper = new MyNewsDummy();
- Populator populator = new Populator(queryHelper,
"nl.vpro.mmbase.republisher.domain");
+ EntityConfigLoader entityConfigLoader = new
EntityConfigLoader("nl.vpro.mmbase.republisher.domain");
+ Populator populator = new Populator(entityConfigLoader,
queryHelper);
Node newsNode = queryHelper.getNews();
News news = (News) populator.unmarshallNode(newsNode, "news");
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-06-29 14:36:06 UTC (rev 36472)
+++
speeltuin/ernst/mmbase-republisher/src/test/java/nl/vpro/mmbase/republisher/RepublisherEventListenerTest.java
2009-06-29 14:36:10 UTC (rev 36473)
@@ -5,6 +5,7 @@
import nl.vpro.mmbase.republisher.endpoint.*;
import nl.vpro.mmbase.republisher.serializer.DocumentSerializer;
import nl.vpro.mmbase.republisher.validator.DocumentValidator;
+import nl.vpro.mmbase.vob.EntityConfigLoader;
import nl.vpro.mmbase.vob.Populator;
import org.junit.Before;
@@ -39,12 +40,14 @@
private MyNewsDummy queryHelper;
private CloudProvider cloudProvider;
private Cloud cloud;
+ private EntityConfigLoader entityConfigLoader;
@Before
public void init() {
eventListener = new RepublisherEventListener();
queryHelper = new MyNewsDummy();
- populator = new Populator(queryHelper,
"nl.vpro.mmbase.republisher.domain");
+ entityConfigLoader = new
EntityConfigLoader("nl.vpro.mmbase.republisher.domain");
+ populator = new Populator(entityConfigLoader, queryHelper);
eventListener.setPopulator(populator);
validator = createMock(DocumentValidator.class);
@@ -98,7 +101,9 @@
assertEquals("serialized document",
endPoint.getDocumentModification().getSerializedDocument());
}
-
+ /**
+ * The entity should not be published
+ */
@Test
public void testCreateNodeEventOnNonRootEntity() {
//setup
@@ -116,6 +121,9 @@
}
+
+
+
/**
* updated node events that map to a root entity should republish this
entity when it is valid
*/
@@ -128,10 +136,30 @@
* updated node events that map to a non root entity should find all
aggregating
* root entities, and publish them when they are valid
*/
+ @Test
public void TestUpdateNodeEventOnNonrootEntity(){
}
+ /**
+ * if a node has changed that is aggregated by a root entity, it should
publish
+ */
+ @Test
+ public void TestUpdateNodeEventOnNodeAggregatedByRootEntity(){
+
+ }
+
+ /**
+ * if an node has changed that is aggregated by a non-root entity, all
root entities should
+ * be published.
+ * TODO: a node can be aggregated by more than one entity. This will
normally not happen, and
+ * should be implemented at a later time.
+ */
+ public void TestUpdateNodeEventOnNodeAggregatedByNonRootEntity(){
+
+ }
+
+
private NodeEvent createNodeEvent(String nodeType, int nodenr, int type){
return new NodeEvent("localhost", nodeType, nodenr, null, null, type);
}
_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs