incubator-oodt-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ke...@apache.org
Subject svn commit: r925913 [2/2] - in /incubator/oodt/agility/agile-oodt/trunk: ./ docs/ oodt/ oodt/tests/
Date Sun, 21 Mar 2010 22:08:02 GMT
Added: incubator/oodt/agility/agile-oodt/trunk/oodt/tests/profileTest.py
URL: http://svn.apache.org/viewvc/incubator/oodt/agility/agile-oodt/trunk/oodt/tests/profileTest.py?rev=925913&view=auto
==============================================================================
--- incubator/oodt/agility/agile-oodt/trunk/oodt/tests/profileTest.py (added)
+++ incubator/oodt/agility/agile-oodt/trunk/oodt/tests/profileTest.py Sun Mar 21 22:08:01 2010
@@ -0,0 +1,239 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt file distributed with
+# this work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you 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.    
+
+'''Unit tests for the `profile` module.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import unittest, xml.dom.minidom
+from oodt.profile import ProfileAttributes, ResourceAttributes, Profile, UnspecifiedProfileElement, RangedProfileElement,\
+    EnumeratedProfileElement
+
+class ProfileAttributesTest(unittest.TestCase):
+    '''Unit test for the ProfileAttributes class.
+    '''
+    def testDefaults(self):
+        '''Test to see if default values are reasonable.
+        '''
+        pa = ProfileAttributes()
+        self.assertEquals('UNKNOWN', pa.id)
+        self.assertEquals('1.0.0', pa.version)
+        self.assertEquals('profile', pa.type)
+        self.assertEquals('active', pa.statusID)
+        self.assertEquals('unclassified', pa.securityType)
+        self.assertEquals('UNKNOWN', pa.parentID)
+        self.assertEquals(0, len(pa.childIDs))
+        self.assertEquals('UNKNOWN', pa.regAuthority)
+        self.assertEquals(0, len(pa.revNotes))
+
+    def testCmp(self):
+        '''Test comparison operators.
+        '''
+        a = ProfileAttributes('1')
+        b = ProfileAttributes('1')
+        c = ProfileAttributes('2')
+        self.assertEquals(a, a)
+        self.assertEquals(a, b)
+        self.assertNotEquals(a, c)
+        self.assert_(a <= a)
+        self.assert_(a <= b)
+        self.assert_(a <= c)
+        self.assert_(a < c)
+        
+    def testXML(self):
+        '''Test XML serialization and re-composition from XML.
+        '''
+        a = ProfileAttributes('1.3.1.9', '2.0.0', 'profile', 'inactive', 'classified', '1.3.1', ['1.3.1.9.1', '1.3.1.9.2'],
+            'NASA', ['Updated', 'Created'])
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        b = ProfileAttributes(node=node)
+        self.assertEquals(a, b)
+        
+    def testXMLValidity(self):
+        '''Test to see if all required XML elements are in there.
+        '''
+        a = ProfileAttributes('1.3.1.9', '2.0.0', 'profile', 'inactive', 'classified', '1.3.1', ['1.3.1.9.1', '1.3.1.9.2'],
+            'NASA', ['Updated', 'Created'])
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        self.assertEquals('profAttributes', node.nodeName)
+        childElements = [n.nodeName for n in node.childNodes]
+        self.assertEquals([u'profId', u'profVersion', u'profType', u'profStatusId', u'profSecurityType', u'profParentId',
+            u'profChildId', u'profChildId', u'profRegAuthority', u'profRevisionNote', u'profRevisionNote'],
+            childElements)
+    
+    def testInstances(self):
+        '''Test to ensure instances don't share instance data.
+        '''
+        a = ProfileAttributes(id='1')
+        b = ProfileAttributes(id='2')
+        self.assertNotEquals(a, b)
+        a.childIDs.append('3')
+        self.assertNotEquals(a.childIDs, b.childIDs)
+        a.revNotes.append('Uhhhhh, spam?')
+        self.assertNotEquals(a.revNotes, b.revNotes)
+    
+    
+class ResourceAttributesTest(unittest.TestCase):
+    '''Unit test for the ResourceAttributes class.
+    '''
+    def testDefaults(self):
+        '''Test if default values are reasonable.
+        '''
+        ra = ResourceAttributes()
+        self.assertEquals('UNKNOWN', ra.identifier)
+        self.assertEquals('UNKNOWN', ra.title)
+        self.assertEquals(0, len(ra.formats))
+        self.assertEquals('UNKNOWN', ra.description)
+        self.assertEquals(0, len(ra.creators))
+        self.assertEquals(0, len(ra.subjects))
+        self.assertEquals(0, len(ra.publishers))
+        self.assertEquals(0, len(ra.contributors))
+        self.assertEquals(0, len(ra.dates))
+        self.assertEquals(0, len(ra.types))
+        self.assertEquals(0, len(ra.sources))
+        self.assertEquals(0, len(ra.languages))
+        self.assertEquals(0, len(ra.relations))
+        self.assertEquals(0, len(ra.coverages))
+        self.assertEquals(0, len(ra.rights))
+        self.assertEquals(0, len(ra.contexts))
+        self.assertEquals('UNKNOWN', ra.aggregation)
+        self.assertEquals('UNKNOWN', ra.resClass)
+        self.assertEquals(0, len(ra.locations))
+    
+    def testCmp(self):
+        '''Test comparison operations.
+        '''
+        a = ResourceAttributes('uri:fish', 'Fish', ['text/html'], 'A book about fish.')
+        b = ResourceAttributes('uri:fish', 'Fish', ['text/html'], 'A book about fish.')
+        c = ResourceAttributes('uri:clams', 'Clams', ['text/html'], 'A book about clams.')
+        self.assertEquals(a, a)
+        self.assertEquals(a, b)
+        self.assertNotEquals(a, c)
+        self.assert_(a <= b)
+        self.assert_(a >= c)
+        self.assert_(a > c)
+        self.assert_(a <= a)
+    
+    def testXML(self):
+        '''Test XML serialization and recomposition from XML.
+        '''
+        a = ResourceAttributes('uri:fish', 'Fish', ['text/html'], 'A book about fish.')
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        b = ResourceAttributes(node=node)
+        self.assertEquals(a, b)
+    
+    def testXMLValidity(self):
+        '''Test to see if all required XML elements are in there.
+        '''
+        a = ResourceAttributes('uri:anus', 'Anus', ['text/html'], 'The anus, rectum, and other parts of the bum.',
+            ['Buttman'], ['butts', 'henies', 'booties'], ['Butts and Co Publishing'], ['Dr Eugene Bottomman, III'],
+            [], ['reference'], ['The Big Book of Booty'], ['en'], ['Buttholes and other oddities'],
+            ['anatomy'], ['Cannot touch this'], ['system.buttServer'], 'granule', 'system.buttServer',
+            ['http://butt.info/butt'])
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        childElements = [n.nodeName for n in node.childNodes]       
+        self.assertEquals([u'Identifier', u'Title', u'Format', u'Description', u'Creator', u'Subject', u'Subject',
+            u'Subject', u'Publisher', u'Contributor', u'Type', u'Source', u'Language', u'Relation', u'Coverage',
+            u'Rights', u'resContext', u'resAggregation', u'resClass', u'resLocation'], childElements)
+    
+    def testInstances(self):
+        '''Test to ensure instances don't share instance data.
+        '''
+        a = ResourceAttributes()
+        b = ResourceAttributes()
+        a.formats.append('text/xml')
+        a.creators.append('Dennis Moore')
+        a.subjects.append('Silliness')
+        a.publishers.append('BBC')
+        a.contributors.append('Nigel')
+        a.types.append('Video')
+        a.languages.append('en')
+        a.relations.append('Fawlty Towers')
+        a.coverages.append('1970')
+        a.rights.append('Abused')
+        a.contexts.append('humor')
+        a.locations.append('http://bbc.co.uk/')
+        self.assertNotEquals(a.formats, b.formats)
+        self.assertNotEquals(a.creators, b.creators)
+        self.assertNotEquals(a.subjects, b.subjects)
+        self.assertNotEquals(a.publishers, b.publishers)
+        self.assertNotEquals(a.contributors, b.contributors)
+        self.assertNotEquals(a.types, b.types)
+        self.assertNotEquals(a.languages, b.languages)
+        self.assertNotEquals(a.relations, b.relations)
+        self.assertNotEquals(a.coverages, b.coverages)
+        self.assertNotEquals(a.rights, b.rights)
+        self.assertNotEquals(a.contexts, b.contexts)
+        self.assertNotEquals(a.locations, b.locations)
+    
+
+class ProfileTest(unittest.TestCase):
+    '''Unit test for class Profile.
+    '''
+    def testCmp(self):
+        a = Profile()
+        b = Profile()
+        self.assertEquals(a, b)
+        
+    def testXML(self):
+        '''Test XML serialization and recomposition from XML.
+        '''
+        a = Profile()
+        doc = xml.dom.minidom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        b = Profile(node=node)
+        self.assertEquals(a, b)
+
+        x = UnspecifiedProfileElement('tastiness', 'How tasty it was', 'char', 'subjective', ['yumminess'],
+            'This is highly subjective.')
+        y = EnumeratedProfileElement('meal', 'What meal was eaten', 'char', 'meal', ['serving'], 'Typical values',
+            ['Breakfast', 'Brunch', 'Lunch', 'Dinner'])
+        z = RangedProfileElement('spicyness', 'How spicy it was', 'float', 'scovilles', ['piquancy'],
+            'Hotter the better, I say', 0.0, 1000000.0)
+        a.profElements['tastiness'], a.profElements['meal'], a.profElements['spicyness'] = x, y, z
+        node = a.toXML(doc)
+        b = Profile(node=node)
+        self.assertEquals(a, b)
+
+    def testInstances(self):
+        '''Test to ensure isntances don't share isntance data.
+        '''
+        a = Profile()
+        b = Profile()
+        self.assertEquals(a, b)
+        a.profElements['a'] = 'b'
+        self.assertNotEquals(a, b)
+    
+
+def test_suite():
+    '''Make the test suite.
+    '''
+    import doctest
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(ProfileAttributesTest))
+    suite.addTest(unittest.makeSuite(ResourceAttributesTest))
+    suite.addTest(unittest.makeSuite(ProfileTest))
+    return suite
+    
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: incubator/oodt/agility/agile-oodt/trunk/oodt/tests/queryTest.py
URL: http://svn.apache.org/viewvc/incubator/oodt/agility/agile-oodt/trunk/oodt/tests/queryTest.py?rev=925913&view=auto
==============================================================================
--- incubator/oodt/agility/agile-oodt/trunk/oodt/tests/queryTest.py (added)
+++ incubator/oodt/agility/agile-oodt/trunk/oodt/tests/queryTest.py Sun Mar 21 22:08:01 2010
@@ -0,0 +1,341 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt file distributed with
+# this work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you 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.    
+
+'''Unit tests for the query module.
+
+This module tests various query classes and the query expression parser.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import unittest, xml.dom, oodt.xmlutils
+from oodt.query import QueryElement, QueryHeader, QueryResult, Query, _parseQuery, ExpressionParseError
+
+class QueryElementTest(unittest.TestCase):
+    '''Test the `QueryElement` class.
+    '''
+    def testDefaults(self):
+        '''Test to see if defaults are reasonable.
+        '''
+        qe = QueryElement()
+        self.assertEqual('UNKNOWN', qe.role)
+        self.assertEqual('UNKNOWN', qe.value)
+
+    def testArgs(self):
+        '''Test to see if initializer arguments are used.
+        '''
+        qe = QueryElement(role='role', value='value')
+        self.assertEqual('role', qe.role)
+        self.assertEqual('value', qe.value)
+    
+    def testComparisons(self):
+        '''Test comparison operators.
+        '''
+        a = QueryElement('a', '1')
+        b = QueryElement('a', '1')
+        c = QueryElement('b', '1')
+        d = QueryElement('a', '2')
+        self.assertEqual(a, a)
+        self.assertEqual(a, b)
+        self.assertEqual(b, a)
+        self.assertNotEqual(a, c)
+        self.assertNotEqual(c, a)
+        self.assertNotEqual(a, d)
+        self.assertNotEqual(d, a)
+        self.assertNotEqual(c, d)
+        self.assert_(a <= a)
+        self.assert_(a <= c)
+        self.assert_(a < c)
+        self.assert_(a <= d)
+        self.assert_(a < d)
+    
+    def testBadArgs(self):
+        '''Test reactions to bad arugments.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        self.assertRaises(ValueError, QueryElement, node=doc.createElement('notAQueryElement'))
+    
+    def testXML(self):
+        '''Test XML serialization.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        q1 = QueryElement(role='a', value='1')
+        root = q1.toXML(doc)
+        self.assertEqual('queryElement', root.nodeName)
+        for child in root.childNodes:
+            if 'tokenRole' == child.nodeName:
+                self.assertEquals('a', oodt.xmlutils.text(child))
+            elif 'tokenValue' == child.nodeName:
+                self.assertEquals('1', oodt.xmlutils.text(child))
+            else:
+                self.fail('Unknown node "' + child.nodeName + '" in XML result')
+
+        q2 = QueryElement(node=root)
+        self.assertEqual(q1, q2)
+
+        root = doc.createElement('queryElement')
+        doc.appendChild(root)
+        elem = doc.createElement('tokenRole')
+        root.appendChild(elem)
+        elem.appendChild(doc.createTextNode('a'))
+        elem = doc.createElement('tokenValue')
+        root.appendChild(elem)
+        elem.appendChild(doc.createTextNode('2'))
+        q3 = QueryElement(node=root)
+        self.assertNotEqual(q1, q3)
+    
+
+_QUERY_HEADER_ATTRS = {
+    'queryId': 'id',
+    'queryTitle': 'title',
+    'queryDesc': 'desc',
+    'queryType': 'type',
+    'queryStatusId': 'status',
+    'querySecurityType': 'security',
+    'queryRevisionNote': 'rev',
+    'queryDataDictId': 'dataDict'
+}
+
+class QueryHeaderTest(unittest.TestCase):
+    '''Unit test for the `QueryHeader` class.
+    '''
+    def testDefaults(self):
+        '''Test if defaults are reasonable.
+        '''
+        qh = QueryHeader()
+        self.assertEqual('UNKNOWN', qh.id)
+        self.assertEqual('UNKNOWN', qh.title)
+        self.assertEqual('UNKNOWN', qh.desc)
+        self.assertEqual('QUERY', qh.type)
+        self.assertEqual('ACTIVE', qh.status)
+        self.assertEqual('UNKNOWN', qh.security)
+        self.assertEqual('2005-10-01 SCK v0.0.0 Under Development', qh.rev)
+        self.assertEqual('UNKNOWN', qh.dataDict)
+
+    def testArgs(self):
+        '''Test if initializer arguments are used.
+        '''
+        qh = QueryHeader('id', 'title', 'desc', 'type', 'status', 'security', 'rev', 'dataDict')
+        self.assertEqual(qh.id, 'id')
+        self.assertEqual(qh.title, 'title')
+        self.assertEqual(qh.desc, 'desc')
+        self.assertEqual(qh.type, 'type')
+        self.assertEqual(qh.status, 'status')
+        self.assertEqual(qh.security, 'security')
+        self.assertEqual(qh.rev, 'rev')
+        self.assertEqual(qh.dataDict, 'dataDict')
+
+    def testBadArgs(self):
+        '''Test reaction to bad arguments.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        self.assertRaises(ValueError, QueryHeader, node=doc.createElement('notAQueryHeader'))
+
+    def testXML(self):
+        '''Test XML serialization.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        q1 = QueryHeader('id', 'title', 'desc', 'type', 'status', 'security', 'rev', 'dataDict')
+        root = q1.toXML(doc)
+        self.assertEqual('queryAttributes', root.nodeName)
+        for child in root.childNodes:
+            self.check(child.nodeName, oodt.xmlutils.text(child))
+        q2 = QueryHeader(node=root)
+        self.assertEqual(q1, q2)
+
+    def check(self, name, value):
+        '''Check if the given tag name is valid.
+        '''
+        if name in _QUERY_HEADER_ATTRS:
+            self.assertEqual(value, _QUERY_HEADER_ATTRS[name])
+        else:
+            fail('Unknown element ' + name + ' in query header')
+    
+
+class QueryResultTest(unittest.TestCase):
+    '''Unit test for the `QueryResults` class.
+    '''
+    def testDefaults(self):
+        '''Test if defaults are reasonable.
+        '''
+        qr = QueryResult()
+        self.assertEquals(0, len(qr.results))
+        self.assertEquals(0, len(qr))
+        self.assertRaises(IndexError, qr.__getitem__, 0)
+
+    def testBadArgs(self):
+        '''Test reaction to bad arguments.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        self.assertRaises(ValueError, QueryResult, node=doc.createElement('notAQueryResult'))
+
+    def testXML(self):
+        '''Test XML serialization.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        q1 = QueryResult()
+        root = q1.toXML(doc)
+        self.assertEqual('queryResultSet', root.nodeName)
+        q2 = QueryResult(node=root)
+        self.assertEqual(q1, q2)
+    
+
+class QueryTest(unittest.TestCase):
+    '''Unit test for the `Query` class.
+    '''
+    def testDefaults(self):
+        '''Test if defaults are reasonable.
+        '''
+        q = Query()
+        self.assertEqual(QueryHeader(), q.header)
+        self.assertEqual('ATTRIBUTE', q.resultModeID)
+        self.assertEqual('BROADCAST', q.propType)
+        self.assertEqual('N/A', q.propLevels)
+        self.assertEqual(1, q.maxResults)
+        self.assertEqual(0, len(q.mimeAccept))
+
+    def testParser(self):
+        '''Test the query expresion parser.
+        '''
+        # Empty
+        self.assertEqual(([], []), _parseQuery(''))
+        
+        # Simple
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='EQ') ], []), _parseQuery('x = 1'))
+
+        # Logical or
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),      
+            QueryElement(role='RELOP', value='LT'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='-2'), QueryElement(role='RELOP', value='GT'),
+            QueryElement(role='LOGOP', value='OR') ], []), _parseQuery('x < 1 or y > -2'))
+
+        # Logical and has higher precendence
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='LE'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='2'), QueryElement(role='RELOP', value='GE'),
+            QueryElement(role='elemName', value='z'), QueryElement(role='LITERAL', value='-3.96'),
+            QueryElement(role='RELOP', value='NE'), QueryElement(role='LOGOP', value='AND'),
+            QueryElement(role='LOGOP', value='OR') ], []), _parseQuery('x <= 1 | y >= 2 and z != -3.96'))
+        
+        # Logical or has lower precedence
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='LT'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='2'), QueryElement(role='RELOP', value='GT'),
+            QueryElement(role='LOGOP', value='AND'), QueryElement(role='elemName', value='z'),
+            QueryElement(role='LITERAL', value='3'), QueryElement(role='RELOP', value='NE'), 
+            QueryElement(role='LOGOP', value='OR') ], []), _parseQuery('x LT 1 & y GT 2 or z NE 3'))
+
+        # Parenthesis
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='LE'), QueryElement(role='elemName', value='y'), \
+            QueryElement(role='LITERAL', value='2'), QueryElement(role='RELOP', value='GE'),
+            QueryElement(role='LOGOP', value='OR'), QueryElement(role='elemName', value='z'),
+            QueryElement(role='LITERAL', value='3'), QueryElement(role='RELOP', value='EQ'), 
+            QueryElement(role='LOGOP', value='AND') ], []), _parseQuery('(x LE 1 or y GE 2) and z EQ 3'))
+
+        # Logical not
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='1'),
+            QueryElement(role='RELOP', value='LE'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='2'), QueryElement(role='RELOP', value='GE'),
+            QueryElement(role='LOGOP', value='OR'), QueryElement(role='LOGOP', value='NOT'),
+            QueryElement(role='elemName', value='z'), QueryElement(role='LITERAL', value='3'),
+            QueryElement(role='RELOP', value='EQ'), QueryElement(role='LOGOP', value='NOT'),
+            QueryElement(role='LOGOP', value='AND') ], []), _parseQuery('not (x LE 1 or y GE 2) and ! z EQ 3'))
+
+        # Quoted strings
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='Fish Poop'),
+            QueryElement(role='RELOP', value='EQ'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='Monkey Poop'), QueryElement(role='RELOP', value='EQ'),
+            QueryElement(role='LOGOP', value='AND') ], []),
+            _parseQuery("""x = "Fish Poop" and y = 'Monkey Poop'"""))
+                
+        # RETURN elements
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='Fish Poop'),
+            QueryElement(role='RELOP', value='EQ'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='Monkey Poop'), QueryElement(role='RELOP', value='EQ'),
+            QueryElement(role='LOGOP', value='AND') ], [QueryElement(role='elemName', value='fish')]),
+            _parseQuery("""x = "Fish Poop" and RETURN > fish and y = 'Monkey Poop'"""))
+        
+        # RETURN at beginning and middle
+        self.assertEqual(([ QueryElement(role='elemName', value='x'), QueryElement(role='LITERAL', value='Fish Poop'),
+            QueryElement(role='RELOP', value='EQ'), QueryElement(role='elemName', value='y'),
+            QueryElement(role='LITERAL', value='Monkey Poop'), QueryElement(role='RELOP', value='EQ'),
+            QueryElement(role='LOGOP', value='AND') ], [QueryElement(role='elemName', value='fish'),
+            QueryElement(role='elemName', value='poop')]),
+            _parseQuery("""RETURN < fish and x = "Fish Poop" and RETURN > poop and y = 'Monkey Poop'"""))
+            
+        # Bad expressions
+        for expr in ('heya', 'RETURN =', 'AND', 'LAT ~ fish', 'NOT', '(', ')'):
+            self.assertRaises(ExpressionParseError, _parseQuery, expr)
+            
+        # Unusual symbols
+        self.assertEqual(([QueryElement('elemName', 'DATA_SET_ID'), QueryElement('LITERAL', 'ARCB-L-RTLS-3-70CM-V1.0'),
+            QueryElement('RELOP', 'EQ')], []), _parseQuery('''DATA_SET_ID = ARCB-L-RTLS-3-70CM-V1.0'''))
+        self.assertEqual(([QueryElement('elemName', 'file'), QueryElement('LITERAL', '/usr/local/bin/poop'),
+            QueryElement('RELOP', 'EQ')], []), _parseQuery('''file = /usr/local/bin/poop'''))
+        self.assertEqual(([QueryElement('elemName', 'start_time'), QueryElement('LITERAL', '2006-02-06T13:12:13'),
+            QueryElement('RELOP', 'EQ')], []), _parseQuery('''start_time = 2006-02-06T13:12:13'''))
+    
+    def testCmp(self):
+        '''Test comparison operators.
+        '''
+        a = Query('lat > 3 and lon < -92.6')
+        b = Query('lat > 3 and lon < -92.6')
+        c = Query('lat < 3 and lon > -92.6')
+        self.assert_(a == a)
+        self.assert_(a == b)
+        self.assert_(a < c)
+        self.assert_(c > a)
+        self.assert_(a <= b)
+        self.assert_(a >= b)
+        self.assert_(a <= c)
+        self.assert_(c >= a)
+        self.assert_(c != a)
+
+    def testXML(self):
+        '''Test XML serialization.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # namespace URI, qualified Name, doctype
+        q1 = Query('lat > 3 and lon < -92.6')
+        root = q1.toXML(doc)
+        self.assertEqual('query', root.nodeName)
+        q2 = Query(node=root)
+        self.assertEqual(q1, q2)
+    
+
+def test_suite():
+    '''Create the suite of tests.
+    '''
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(QueryElementTest))
+    suite.addTest(unittest.makeSuite(QueryHeaderTest))
+    suite.addTest(unittest.makeSuite(QueryResultTest))
+    suite.addTest(unittest.makeSuite(QueryTest))
+    return suite
+    
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+    

Added: incubator/oodt/agility/agile-oodt/trunk/oodt/tests/xmlutilsTest.py
URL: http://svn.apache.org/viewvc/incubator/oodt/agility/agile-oodt/trunk/oodt/tests/xmlutilsTest.py?rev=925913&view=auto
==============================================================================
--- incubator/oodt/agility/agile-oodt/trunk/oodt/tests/xmlutilsTest.py (added)
+++ incubator/oodt/agility/agile-oodt/trunk/oodt/tests/xmlutilsTest.py Sun Mar 21 22:08:01 2010
@@ -0,0 +1,109 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt file distributed with
+# this work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you 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.    
+
+'''Unit tests for the `xmlutils` module.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import unittest, xml.dom, oodt.xmlutils
+from oodt.xmlutils import DocumentableField
+
+class XMLTest(unittest.TestCase):
+    '''Unit test the XML utilities.
+    '''
+    def testText(self):
+        '''Test getting text from nodes.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # ns URI, qual name, doctype
+        root = doc.createElement('root')
+        root.appendChild(doc.createTextNode('Hello'))
+        child = doc.createElement('child')
+        root.appendChild(child)
+        root.appendChild(doc.createCDATASection('world'))
+        child.appendChild(doc.createTextNode('cruel'))
+        empty = doc.createElement('empty')
+        root.appendChild(empty)
+
+        self.assertEquals('cruel', oodt.xmlutils.text(child))
+        self.assertEquals(0, len(oodt.xmlutils.text(empty)))
+        self.assertEquals('Hellocruelworld', oodt.xmlutils.text(root))
+    
+    def testAdds(self):
+        '''Test adding things to nodes.
+        '''
+        domImpl = xml.dom.getDOMImplementation()
+        doc = domImpl.createDocument(None, None, None) # ns URI, qual name, doctype
+        root = doc.createElement('root')
+
+        oodt.xmlutils.add(root, 'first')
+        self.assertEquals(0, len(oodt.xmlutils.text(root)))
+        oodt.xmlutils.add(root, 'second', 'with text')
+        self.assertEquals('with text', oodt.xmlutils.text(root))
+        
+        oodt.xmlutils.add(root, 'number', [str(i) for i in range(1, 4)])
+        self.assertEquals('with text123', oodt.xmlutils.text(root))
+    
+
+class DocumentableTest(unittest.TestCase):
+    '''Unit test the `Documentable` and `DocumentableField` classes.
+    '''
+    def testIt(self):
+        '''Test the `Documentable` and `DocumentableField` classes.
+        '''
+        class X(oodt.xmlutils.Documentable):
+            def __init__(self, mission='UNK', target='UNK', measurements=[], node=None):
+                self.mission, self.target, self.measurements = mission, target, measurements
+                if node is not None:
+                    self.parse(node)
+            def computeValueFromDocument(self, attrName, text):
+                if attrName == 'measurements':
+                    return int(text)
+                else:
+                    return text
+            def getDocumentElementName(self):
+                return 'X'
+            def getDocumentableFields(self):
+                return (DocumentableField('mission', u'MISSION', DocumentableField.SINGLE_VALUE_KIND),
+                DocumentableField('target', u'TARGET', DocumentableField.SINGLE_VALUE_KIND),
+                DocumentableField('measurements', u'MZR', DocumentableField.MULTI_VALUED_KIND))
+            def __eq__(self, other):
+                return (self.mission == other.mission and self.target == other.target
+                    and cmp(self.measurements, other.measurements) == 0)
+            def __str__(self):
+                return '%s,%s:%s' % (self.mission, self.target, self.measurements)
+        a = X('Explorer', 'Moon', [1, 2, 3])
+        doc = xml.dom.getDOMImplementation().createDocument(None, None, None)
+        node = a.toXML(doc)
+        b = X(node=node)
+        self.assertEquals(a, b)
+    
+
+def test_suite():
+    '''Create the suite of tests.
+    '''
+    import doctest
+    suite = unittest.TestSuite()
+    suite.addTest(unittest.makeSuite(XMLTest))
+    suite.addTest(unittest.makeSuite(DocumentableTest))
+    suite.addTest(doctest.DocTestSuite(oodt.xmlutils))
+    return suite
+    
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: incubator/oodt/agility/agile-oodt/trunk/oodt/webgrid.py
URL: http://svn.apache.org/viewvc/incubator/oodt/agility/agile-oodt/trunk/oodt/webgrid.py?rev=925913&view=auto
==============================================================================
--- incubator/oodt/agility/agile-oodt/trunk/oodt/webgrid.py (added)
+++ incubator/oodt/agility/agile-oodt/trunk/oodt/webgrid.py Sun Mar 21 22:08:01 2010
@@ -0,0 +1,226 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt file distributed with
+# this work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you 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.    
+
+'''Agile Web Grid.  HTTP-based profile and product servers.
+'''
+
+__docformat__ = 'restructuredtext'
+
+from oodt.query import Query
+from xml.dom.minidom import parseString, getDOMImplementation
+from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
+import cgi, os, shutil, stat
+
+_validKinds = ('profile', 'product')
+_doc = getDOMImplementation().createDocument(None, None, None) # qname, nsuri, doctype
+    
+class WebGridRequestHandler(BaseHTTPRequestHandler):
+    '''HTTP request handler for Web-Grid requests.  This request handler accepts GET
+    or POST requests and directs them to profile or product handlers.  Additionally,
+    requests to install new handlers, to list currently installed handlers, and to
+    remove handlers by ID are supported.
+    '''
+    def do_POST(self):
+        '''Handle a POST.
+        '''
+        try:
+            length = int(self.headers['content-length'])
+            kind = self.headers['content-type']
+            if kind.endswith('www-form-urlencoded'):
+                if length > 0:
+                    params = cgi.parse_qs(self.rfile.read(length), True, True) # Keep blanks, strict parse
+                else:
+                    params = {}
+                self.__execute(self.path, params)
+            else:
+                raise ValueError('Unknown encoding "%s"' % kind)
+        except Exception, e:
+            self.send_error(500, str(e))
+    
+    def do_GET(self):
+        '''Handle a GET.
+        '''
+        try:
+            index = self.path.find('?')
+            if index >= 0:
+                params = cgi.parse_qs(self.path[index+1:], True, True) # Keep blanks, strict parse
+                path = self.path[0:index]
+            else:
+                params, path = {}, self.path
+            self.__execute(path, params)
+        except Exception, e:
+            self.send_error(500, str(e))
+    
+    def __execute(self, path, params):
+        '''Execute an HTTP request.
+        '''
+        components = path.split('/')
+        if len(components) == 3:
+            context, command = components[1], components[2]
+            if context != self.server.serverID:
+                raise ValueError('Unknown server ID "%s"' % context)
+            func = getattr(self, command)
+            if callable(func):
+                func(params)
+                return
+        raise KeyError('Unknown command')
+    
+    def echo(self, params):
+        '''Debugging method that echoes back the request parameters.
+        '''
+        u = unicode(params)
+        self.send_response(200)
+        self.send_header('Content-type', 'text/plain;charset=utf-8')
+        self.send_header('Content-length', str(len(u)))
+        self.end_headers()
+        self.wfile.write(u)
+    
+    def sendEmptyResponse(self):
+        '''Send an empty response to the HTTP client.
+        '''
+        self.send_response(200)
+        self.send_header('Content-type', 'text/plain;charset=utf-8')
+        self.send_header('Content-length', '0')
+        self.end_headers()
+    
+    def install(self, params):
+        '''Install a new handler.  This will overwrite existing handlers with the
+        same ID.
+        '''
+        handlers = self.server.getHandlers(params['kind'][0])
+        globs = dict(globals())
+        del globs['__name__']
+        # TODO: use rexec or otherwise limit the code than can be uploaded.
+        exec params['code'][0] in globs, globs
+        handlers[params['id'][0]] = globs['handler']
+        self.sendEmptyResponse()
+    
+    def remove(self, params):
+        '''Remove an existing handler.
+        '''
+        handlers = self.server.getHandlers(params['kind'][0])
+        del handlers[params['id'][0]]
+        self.sendEmptyResponse()
+    
+    def list(self, params):
+        '''List installed handlers.
+        '''
+        handlers = {}
+        for kind in _validKinds:
+            handlers[kind] = self.server.getHandlers(kind).keys()
+        handlers = unicode(handlers)
+        self.send_response(200)
+        self.send_header('Content-type', 'text/plain;charset=utf-8')
+        self.send_header('Content-length', str(len(handlers)))
+        self.end_headers()
+        self.wfile.write(handlers)
+    
+    def __createQuery(self, params):
+        '''Create a Query from the request parameters.  This method prefers the
+        xmlq parameter and parses it as an XML document and into a Query object.
+        However, if it's not provided, or fails to parse, it'll use the q parameter,
+        which is expected to be just a query expression.
+        '''
+        try:
+            doc = parseString(params['xmlq'][0])
+            return Query(node=doc.documentElement)
+        except KeyError:
+            return Query(params['q'][0])
+    
+    def sendProduct(self, match):
+        '''Send a matching product.
+        '''
+        self.send_response(200)
+        self.send_header('Content-type', match.contentType)
+        self.send_header('Content-length', str(match.length))
+        self.end_headers()
+        shutil.copyfileobj(match.data, self.wfile)
+        self.log_request(200, match.length)
+    
+    def prod(self, params):
+        '''Handle a product query.
+        '''
+        query = self.__createQuery(params)
+        for handler in self.server.getHandlers('product'):
+            matches = handler.query(query)
+            if len(matches) > 0:
+                self.sendProduct(matches[0])
+        self.send_error(404, 'No matching products')
+    
+    def prof(self, params):
+        '''Handle a profile query.
+        '''
+        query = self.__createQuery(params)
+        tmp = os.tmpfile()
+        tmp.writelines((u'<?xml version="1.0" encoding="UTF-8"?>\n',
+            u'<!DOCTYPE profiles PUBLIC "-//JPL//DTD Profile 1.1//EN"\n',
+            u'  "http://oodt.jpl.nasa.gov/grid-profile/dtd/prof.dtd">\n',
+            u'<profiles>\n'))
+        for handler in self.server.getHandlers('profile').itervalues():
+            for profile in handler.query(query):
+                node = profile.toXML(_doc)
+                tmp.write(node.toxml())
+        tmp.write(u'</profiles>')
+        tmp.flush()
+        tmp.seek(0L)
+        self.send_response(200)
+        self.send_header('Content-type', 'text/xml;charset=utf-8')
+        size = os.fstat(tmp.fileno())[stat.ST_SIZE]
+        self.send_header('Content-length', str(size))
+        self.end_headers()
+        shutil.copyfileobj(tmp, self.wfile)
+        self.log_request(200, size)
+    
+
+class WebGridServer(HTTPServer):
+    '''Web grid HTTP server.  This server handles incoming HTTP requests and directs them to a
+    WebGridRequestHandler.  It also contains the server's ID, and the sequences of profile and
+    product handlers.
+    '''
+    def __init__(self, addr, serverID):
+        '''Initialize by saving the server ID and creating empty sequences of profile
+        and product handlers.
+        '''
+        HTTPServer.__init__(self, addr, WebGridRequestHandler)
+        self.serverID = serverID
+        self.__handlers = {}
+        for kind in _validKinds:
+            self.__handlers[kind] = {}
+    
+    def getHandlers(self, kind):
+        '''Get the map of handlers for the given kind, which is either "product" or "profile".
+        '''
+        if kind not in _validKinds:
+            raise ValueError('Invalid handler kind "%s"' % kind)
+        return self.__handlers[kind]
+    
+
+def _main():
+    '''Run the web grid server.
+    '''
+    import sys
+    try:
+        serverID = sys.argv[1]
+    except IndexError:
+        serverID = 'oodt'
+    listenAddr = ('', 7576)
+    httpd = WebGridServer(listenAddr, serverID)
+    httpd.serve_forever()
+    
+
+if __name__ == '__main__':
+    _main()

Added: incubator/oodt/agility/agile-oodt/trunk/oodt/xmlutils.py
URL: http://svn.apache.org/viewvc/incubator/oodt/agility/agile-oodt/trunk/oodt/xmlutils.py?rev=925913&view=auto
==============================================================================
--- incubator/oodt/agility/agile-oodt/trunk/oodt/xmlutils.py (added)
+++ incubator/oodt/agility/agile-oodt/trunk/oodt/xmlutils.py Sun Mar 21 22:08:01 2010
@@ -0,0 +1,209 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt file distributed with
+# this work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you 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.    
+
+'''Object Oriented Data Technology XML utilities. These are some simple utilities
+that make working with rather obtuse DOM API less painful.
+'''
+
+__docformat__ = 'restructuredtext'
+
+import string
+import xml.dom
+    
+def text(node):
+    '''Return the text under the given node.  Text and CDATA nodes simply return
+    their content.  Otherwise, text is gathered in a depth-first left-to-right
+    traversal of the node, building up text as we go along.
+    
+    >>> import xml.dom
+    >>> domImpl = xml.dom.getDOMImplementation()
+    >>> doc = domImpl.createDocument(None, None, None)
+    >>> root = doc.createElement('root')
+    >>> root.appendChild(doc.createTextNode('alpha')) # doctest: +ELLIPSIS
+    <DOM Text node...>
+    >>> text(root)
+    'alpha'
+    >>> child = root.appendChild(doc.createElement('child'))
+    >>> text(child.appendChild(doc.createCDATASection('beta')))
+    'beta'
+    >>> text(root)
+    'alphabeta'
+    '''
+    strings = []
+    _text0(node, strings)
+    return string.join(strings, '') # no separator
+    
+
+def _text0(node, strings):
+    '''Add the text under the given node to the list of strings.
+    '''
+    if node.nodeType == xml.dom.Node.CDATA_SECTION_NODE:
+        strings.append(node.nodeValue)
+    elif node.nodeType == xml.dom.Node.TEXT_NODE:
+        strings.append(node.nodeValue)
+    for child in node.childNodes:
+        _text0(child, strings)
+    
+
+def add(node, elementName, value=None):
+    '''Add an element under the given node.  Optionally, the value text is added to the element.
+    Returns the original node, handy for chaining calls together.  If the value is a sequence,
+    then the element is added multiple times for each item in the sequence, using the item
+    as the text.
+
+    >>> from xml.dom.minidom import getDOMImplementation
+    >>> doc = getDOMImplementation().createDocument(None, None, None)
+    >>> root = doc.createElement('root')
+    >>> root.toxml()
+    '<root/>'
+    >>> add(root, 'empty').toxml()
+    '<root><empty/></root>'
+    >>> add(root, 'full', 'of text').toxml()
+    '<root><empty/><full>of text</full></root>'
+    >>> add(root, 'item', [str(i) for i in range(1, 4)]).toxml()
+    '<root><empty/><full>of text</full><item>1</item><item>2</item><item>3</item></root>'
+    '''
+    owner = node.ownerDocument
+    if isinstance(value, basestring):
+        elem = owner.createElement(elementName)
+        node.appendChild(elem)
+        elem.appendChild(owner.createTextNode(value))
+    elif value is not None:
+        for i in value:
+            elem = owner.createElement(elementName)
+            node.appendChild(elem)
+            elem.appendChild(owner.createTextNode(i))
+    else:
+        node.appendChild(owner.createElement(elementName))
+    return node
+    
+
+class DocumentableField(object):
+    '''A documentable field is an attribute of an object that we can serialize into XML.
+    '''
+    SINGLE_VALUE_KIND = 1
+    MULTI_VALUED_KIND = 2
+    DOCUMENTABLE_KIND = 3
+
+    def __init__(self, attrName, elemName, kind):
+        '''Initialize a documentable field with attrName (name of attribute in object),
+        elemName (name to use for XML element) and kind, which is one of the DOCUMENTABLE_*
+        constants.
+        '''
+        self.attrName = attrName
+        self.elemName = elemName
+        if kind not in (DocumentableField.SINGLE_VALUE_KIND, DocumentableField.MULTI_VALUED_KIND,
+            DocumentableField.DOCUMENTABLE_KIND):
+            raise ValueError('Invalid kind %d' % kind)
+        self.kind = kind
+    
+    def __cmp__(self, other):
+        attrName = cmp(self.attrName, other.attrName)
+        if attrName < 0:
+            return -1
+        elif attrName == 0:
+            elemName = cmp(self.elemName, other.elemName)
+            if elemName < 0:
+                return -1
+            elif elemName == 0:
+                return cmp(self.kind, other.kind)
+        return 1
+    
+    def __hash__(self):
+        return hash(self.attrName) ^ hash(self.elemName) ^ self.kind
+    
+
+class Documentable(object):
+    '''An object that can be documented into XML and parsed from an XML document.
+    '''
+    def getDocumentElementName(self):
+        '''Get the XML tag name.  Subclasses must override this
+        otherwise they get the tag name `UNKNOWN`.
+        '''
+        return 'UNKNOWN'
+        
+    def getDocumentableFields(self):
+        '''Get the sequence of documentable attributes.  Subclasses should override this
+        with a sequence of `DocumentableField` objects.  By default, we return an empty
+        sequence.
+        '''
+        return []
+    
+    def toXML(self, owner):
+        '''Convert this object into XML owned by the given `owner` document.
+        '''
+        root = owner.createElement(self.getDocumentElementName())
+        for df in self.getDocumentableFields():
+            if df.kind == DocumentableField.SINGLE_VALUE_KIND:
+                add(root, df.elemName, str(getattr(self, df.attrName)))
+            elif df.kind == DocumentableField.MULTI_VALUED_KIND:
+                add(root, df.elemName, [str(value) for value in getattr(self, df.attrName)])
+            else:
+                root.appendChild(getattr(self, df.attrName).toXML(owner))
+        return root
+    
+    def computeValueFromDocument(self, attrName, text):
+        '''Compute a value for the attribute named `attrName` from the
+        XML text representation `text`.  Subclasses may wish to
+        override this in order to provide custom typing for certain
+        attributes, such as returning an integer or datetime value by
+        parsing the text.  By default, the `text` is returned
+        unmodified as a string.
+        '''
+        return text
+    
+    def parse(self, node):
+        '''Initialize this object from the given XML DOM `node`.
+        '''
+        if node.nodeName != self.getDocumentElementName():
+            raise ValueError('Expected %s element but got %s' % (self.getDocumentElementName(), node.nodeName))
+        fieldMap = dict(zip([i.elemName for i in self.getDocumentableFields()], self.getDocumentableFields()))
+        for child in filter(lambda n: n.nodeType == xml.dom.Node.ELEMENT_NODE, node.childNodes):
+            name = child.nodeName
+            if name in fieldMap:
+                field = fieldMap[name]
+                if field.kind == DocumentableField.SINGLE_VALUE_KIND:
+                    setattr(self, field.attrName, self.computeValueFromDocument(field.attrName, text(child)))
+                elif field.kind == DocumentableField.MULTI_VALUED_KIND:
+                    if not hasattr(self, field.attrName):
+                        setattr(self, field.attrName, [])
+                    getattr(self, field.attrName).append(self.computeValueFromDocument(field.attrName,
+                        text(child)))
+                else:
+                    getattr(self, field.attrName).parse(child)
+    
+    def __cmp__(self, other):
+        '''The documentable fields provide a bonus: we can use them to do comparisons.
+        '''
+        for field in self.getDocumentableFields():
+            attrName = field.attrName
+            mine = getattr(self, attrName)
+            others = getattr(other, attrName)
+            rc = cmp(mine, others)
+            if rc < 0:
+                return -1
+            elif rc > 0:
+                return 1
+        return 0
+    
+    def __hash__(self):
+        '''The documentable fields provide another bonus: we can use them
+        to do hashing.
+        '''
+        return reduce(lambda x, y: hash(x) ^ hash(y), [getattr(self, i.attrName) for i in self.getDocumentableFields()],
+            0x55555555)
+    
\ No newline at end of file

Added: incubator/oodt/agility/agile-oodt/trunk/setup.cfg
URL: http://svn.apache.org/viewvc/incubator/oodt/agility/agile-oodt/trunk/setup.cfg?rev=925913&view=auto
==============================================================================
--- incubator/oodt/agility/agile-oodt/trunk/setup.cfg (added)
+++ incubator/oodt/agility/agile-oodt/trunk/setup.cfg Sun Mar 21 22:08:01 2010
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt file distributed with
+# this work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you 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.    
+
+[egg_info]
+tag_build = .dev
+tag_svn_revision = 1

Added: incubator/oodt/agility/agile-oodt/trunk/setup.py
URL: http://svn.apache.org/viewvc/incubator/oodt/agility/agile-oodt/trunk/setup.py?rev=925913&view=auto
==============================================================================
--- incubator/oodt/agility/agile-oodt/trunk/setup.py (added)
+++ incubator/oodt/agility/agile-oodt/trunk/setup.py Sun Mar 21 22:08:01 2010
@@ -0,0 +1,98 @@
+# encoding: utf-8
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE.txt file distributed with
+# this work for additional information regarding copyright ownership.  The ASF
+# licenses this file to you 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.    
+
+import os.path
+from distribute_setup import use_setuptools
+use_setuptools()
+from setuptools import find_packages, setup
+
+
+# Package data
+# ------------
+
+_name         = 'oodt'
+_version      = '1.0.0'
+_description  = 'Agile OODT'
+_url          = 'http://incubator.apache.org/projects/oodt.html'
+_downloadURL  = 'http://pypi.python.org/pypi/oodt/'
+_author       = 'Sean Kelly'
+_authorEmail  = 'kelly@apache.org'
+_license      = 'Apache 2.0'
+_namespaces   = []
+_testSuite    = 'oodt.tests.test_suite'
+_zipSafe      = True
+_keywords     = 'data grid discovery query optimization object middleware archive catalog index'
+_requirements = []
+_entryPoints  = {
+    'console_scripts': ['webgrid = oodt.webgrid:_main'],
+}
+_classifiers  = [
+    'Environment :: Console',
+    'Environment :: No Input/Output (Daemon)',
+    'Intended Audience :: Developers',
+    'Intended Audience :: Information Technology',
+    'Intended Audience :: Science/Research',
+    'Topic :: Database :: Front-Ends',
+    'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
+    'Topic :: Internet :: WWW/HTTP :: HTTP Servers',
+    'Topic :: Internet :: Z39.50',
+    'Topic :: Scientific/Engineering',
+    'Development Status :: 5 - Production/Stable',
+    'Environment :: Web Environment',
+    'License :: OSI Approved :: Apache Software License',
+    'Operating System :: OS Independent',
+    'Programming Language :: Python',
+    'Topic :: Internet :: WWW/HTTP',
+    'Topic :: Software Development :: Libraries :: Python Modules',
+]
+
+
+# Setup Metadata
+# --------------
+
+def _read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+_header = '*' * len(_name) + '\n' + _name + '\n' + '*' * len(_name)
+_longDescription = '\n\n'.join([
+    _header,
+    _read('README.txt'),
+    _read('docs', 'INSTALL.txt'),
+    _read('docs', 'HISTORY.txt')
+])
+open('doc.txt', 'w').write(_longDescription)
+
+setup(
+    author=_author,
+    author_email=_authorEmail,
+    classifiers=_classifiers,
+    description=_description,
+    download_url=_downloadURL,
+    entry_points=_entryPoints,
+    include_package_data=True,
+    install_requires=_requirements,
+    keywords=_keywords,
+    license=_license,
+    long_description=_longDescription,
+    name=_name,
+    namespace_packages=_namespaces,
+    packages=find_packages(),
+    test_suite=_testSuite,
+    url=_url,
+    version=_version,
+    zip_safe=_zipSafe,
+)



Mime
View raw message