incubator-clerezza-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Henry Story (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (CLEREZZA-603) EzMGraph fails when working with more than one instance
Date Tue, 19 Jul 2011 09:27:58 GMT

    [ https://issues.apache.org/jira/browse/CLEREZZA-603?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13067591#comment-13067591
] 

Henry Story commented on CLEREZZA-603:
--------------------------------------

In that discussion I ended up explaining in detail why the current problem exists. But in
order
to understant the problem one has to first understand what is on in constructs such as the
following:

  reto.a(FOAF.Person)
          -- FOAF.knows --> (
		"http://bblfish.net/#hjs".uri.a(FOAF.Person)
			-- FOAF.name --> "Henry Story"
			-- FOAF.currentProject --> "http://webid.info/".uri
               )

 Starting from the center, let us see how implicits are getting used here:

 1.  "http://bblfish.net/#hjs".uri.a(FOAF.Person) 

  a)   gets transformed into

        new URIRef("http://bblfish.net/#hjs")

     because the .uri method is defined on EzLiteral and there is the 
     implicit def string2lit(str: String) = new EzLiteral(str)

  b)  then it gets transformed into a RichGraphNode - let's call it anon_rgn_hjs - because
the method a(..) is defined there and because of the implicit (call it IMP)

      implicit def toRichGraphNode(resource: Resource) = {
		new RichGraphNode(new GraphNode(resource, baseTc))
	} 

  2. Then the RichGraphNode anon_rgn_hjs is filled out with the FOAF.name and FOAF.currentProject
relations

  3. reto - a rich graph node - is then related by foaf knows to anon_rgn_hjs.resource
       by the following function

		def -->(sub: GraphNode): RichGraphNode = {
			//RichGraphNode.this + sub
			-->(sub.getNode)
		}


   QUESTION: what happens to the graph of anon_rgn_hjs ? How does it get added to the graph
of reto?
   -------- 

  Well this occurs because of the implicit IMP  which this whole issue is questioning the
wisdom of,


     implicit def toRichGraphNode(resource: Resource) = {
		new RichGraphNode(new GraphNode(resource, baseTc))
     } 

   Notice that the implicit created a new GraphNode, whose graph is called "baseTc". But where
does baseTc come from?
Ahah. IMP is part of a trait:

protected trait TcDependentConversions extends TcIndependentConversions {
	
	def baseTc: TripleCollection
	
	implicit def toRichGraphNode(resource: Resource) = {
		new RichGraphNode(new GraphNode(resource, baseTc))
	}
}

And  EzMGraph is defined as extending that trait.

    class EzMGraph(val baseTc: MGraph) extends AbstractMGraph with TcDependentConversions


putting it together:
-------------------

When you create a new EzMGraph - call it ez - you create an object with the toRichGraphNode()
implicit, whose baseTc set to that Graph's tc collection. The you

  import ez._ 

to import that implicit so that it becomes available for usage. Of course that implicit is
tightly tied to ez. 
So this explains then how anon_rgn_hjs gets added to ez. It's because when in 1b above when

new URIRef("http://bblfish.net/#hjs") was transformed into a RichGraphNode using the IMP implicit,
the
graph of ez was added as its backing store.

Ok so all that is really clever! But just a bit too clever by half, sadly.

Remember that the point of this patch is to fix the real problem with the current framework,
which is that
currently if you have two graphs you need to keep writing the import statements every time
you wish to 
change graph. Like this:

  import ez1._ 
  ez1.b_("reto") -- FOAF.homepage --> "http://bblfish.net/".uri 

  import ez2._ 
  ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri 

  import ez1._ 
  ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri 


This is very error prone it seems to me.

And the reason we have that error, is because of the an implicit that is tied
to a hidden variable. This is very clearly a Scala anti-pattern.


> EzMGraph fails when working with more than one instance
> -------------------------------------------------------
>
>                 Key: CLEREZZA-603
>                 URL: https://issues.apache.org/jira/browse/CLEREZZA-603
>             Project: Clerezza
>          Issue Type: Bug
>            Reporter: Henry Story
>            Priority: Critical
>         Attachments: 0001-CLEREZZA-603-EzMGraph.bnode-now-returns-a-RichGraphN.patch
>
>   Original Estimate: 1h
>  Remaining Estimate: 1h
>
> All the EzMGraph test cases currently assume that there is only one ez graph available
per method.  
> When one adds two EzMGraphs together in some code one gets a failure as the following
test case shows when run in EzMGraphTest class:
> 	@Test
> 	def twographs {
> 		val ez1 = new EzMGraph() {(
> 			b_("reto") -- FOAF.name --> "Reto Bachman-Gmür".lang("rm")
> 		)}
> 		Assert.assertEquals("the two graphs should be equal",1,ez1.size)
> 		import ez1._
> 		ez1.b_("reto") -- FOAF.homepage --> "http://bblfish.net/".uri
> 		Assert.assertEquals("ez1 has grown by one",2,ez1.size)
> 		//now a second graph
> 		val ez2 = new EzMGraph() {(
> 			b_("hjs") -- FOAF.name --> "Henry Story"
> 		)}
> 		ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
>                //both of these tests fail
> 		Assert.assertEquals("ez1 is the same size as it used to be",2,ez1.size)
> 		Assert.assertEquals("ez2 has grown by one",2,ez2.size)
> 	}
> This is caused by a bit too much implicit magic.  EzMGraph extends TcDependentConversions
which is defined as
> protected trait TcDependentConversions {
> 	
> 	def baseTc: TripleCollection
> 	
> 	implicit def toRichGraphNode(resource: Resource) = {
> 		new RichGraphNode(new GraphNode(resource, baseTc))
> 	}
> }
> So when developing this one has to import the toRichGraphNode method for the TripleCollection
one is using.
> Hence you will see the first
> 		import ez1._
> above. The errors can be avoided if one enters a new import for ez2._ just before code
using ez2 . The problem is that this will never be picked up by the compiler and the error
will only be found at runtime. But then code would look like this
> 		import ez1._
> 		ez1.b_("reto") -- FOAF.homepage --> "http://bblfish.net/".uri
>                 import ez2._
> 		ez2.b_("hjs") -- FOAF.homepage --> "http://bblfish.net/".uri
> 		import ez1._
>                	ez1.b_("reto") -- FOAF.currentProject --> "http://clerezza.org/".uri
> The answer to this problem is simply to have the ez1.b_ method return a RichGraphNode
directly containing the EzGraphNode from which it was called.
> It makes more sense anyway to have a Graph return a GraphNode when one asks for a node
from it. Certainly a BNode outside of the context of a graph makes very little sense.
>  

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

Mime
View raw message