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

Reply via email to