<red:code xmlns:red="http://redfoot.sourceforge.net/2001/06/">

  from redfootlib.rdf.const import LABEL, TYPE
  from redfootlib.rdf.objects import resource, literal
  from redfootlib.rdf.query.functors import filter, s, remove_duplicates

  from redfootlib.neighbour_manager import NEIGHBOUR, CONNECTED, YES, NO

  <red:module name="Neighbours">

    <red:facet name="neighbours">
      <H2>Neighbours</H2>

      <DIV class="content_area">
        <H3 CLASS="content_header">Connected</H3>
        <TABLE>

        <red:exec>
          for subject in self.app.rednode.neighbourhood.subjects_by_type(NEIGHBOUR, CONNECTED, YES):
             self._connected_row(subject)
        </red:exec>        
        
        </TABLE>
      </DIV>

      <DIV class="content_area">
        <H3 class="content_header">Other Known</H3>

        <FORM name="other" method="POST" style="margin: 0">
          <INPUT name="uri" value="" type="hidden"/>
          <input name='module_instance' 
                 type='HIDDEN' 
                 value="{self.module_instance}"/>
          <INPUT name="processor" value="" type="hidden"/>          
          <TABLE>

          <red:exec>
            subjects = lambda (s, p, o): s          
            self.app.rednode.neighbourhood.visit(remove_duplicates(filter(self._other_row, s(self.app.rednode.neighbourhood.not_exists, CONNECTED, YES)), subjects), (None, TYPE, NEIGHBOUR))
          </red:exec>
            
          </TABLE>
        </FORM>
      </DIV>

      <DIV class="content_area">
        <SPAN class="content_header">Add Neighbour</SPAN>
        <FORM name="add" method="POST" action="" style="margin: 0">
          <TABLE>
            <TR>
              <TD>URI:</TD>
              <TD><INPUT name="uri" type="text" size="50"/></TD>
            </TR>
            <TR>
              <TD align="right">
                <INPUT value="Add" type="submit"/>
              </TD>
              <TD align="left">
                <INPUT value="Cancel" type="reset"/>
                <INPUT name="processor" value="add_neighbour" type="hidden"/>      
              </TD>
            </TR>
          </TABLE>
        </FORM>
      </DIV>
    </red:facet>

    <red:facet name="_connected_row" args="neighbour">
          <FORM name="main" method="POST" style="margin: 0">
            <TR>
              <TD><red:eval>neighbour</red:eval>
                <INPUT name="uri" value="{neighbour}" type="hidden"/>
              </TD>
              <TD align="right">
                <INPUT value="Disconnect" type="submit"/>
                <INPUT name="processor" value="disconnect_neighbour" type="hidden"/>
              </TD>
            </TR>
          </FORM>
    </red:facet>


    <red:facet name="_other_row" args="neighbour, p, o">
            <TR>
              <TD><red:eval>neighbour</red:eval></TD>
              <TD>
                <INPUT value="Connect" type="button" onclick="other.uri.value='{neighbour}';other.processor.value='connect_neighbour';other.submit()"/>
              </TD>
              <TD align="right">
                <INPUT value="Remove" type="button" onclick="other.uri.value='{neighbour}';other.processor.value='remove_neighbour';other.submit()"/>
              </TD>

              <!-- Make the status red -->
              <TD><red:eval>self.status.get(neighbour, '')</red:eval></TD>
            </TR>
    </red:facet>


    def __init__(self, app):
       super(Neighbours, self).__init__(app)
       self.status = {}

    def __getattr__(self, name):
        if name=="rednode": # default rednode to self.app.rednode
            self.set_rednode(self.app.rednode)
            return self.rednode
        else:
            raise AttributeError
        
    # TODO: does anything in generic/editor/viewer require a rednode
    # or just a TripleStoreIO
    def set_rednode(self, rednode):
        self.rednode = rednode

    def do_disconnect_neighbour(self, request, response):
       uri = request.get_parameter('uri')
       self.app.rednode.disconnect_from(uri)

    def do_connect_neighbour(self, request, response):
       uri = request.get_parameter('uri')
       try:
          self.app.rednode.connect_to(uri)
          self.status[uri] = None
       except Exception, msg:
          self.status[uri] = "%s: %s" % (msg.__class__.__name__, msg)

    def do_remove_neighbour(self, request, response):
       uri = request.get_parameter('uri')
       self.app.rednode.remove_triples(resource(uri), TYPE, NEIGHBOUR)
       self.app.rednode.remove_triples(resource(uri), CONNECTED, None)
       self.status[uri] = None

    def do_add_neighbour(self, request, response):
       uri = request.get_parameter('uri')

       from urlparse import urlparse, urlunparse
       from urllib import quote, quote_plus

       scheme, netloc, url, params, query, fragment = urlparse(uri)
       orig = uri
       url = quote(url, safe="/%")
       query = quote_plus(query, safe="=&amp;")
       uri = urlunparse((scheme, netloc, url, params, query, fragment))
       # TODO: check to see if uri has been further encoded by the
       # above and if so, added a warning message to that effect.
       if uri!=orig:
          self.status[uri] = "URI contained illegal characters. Encoded '%s' as '%s'" % (orig, uri)

       
       self.app.rednode.add(resource(uri), TYPE, NEIGHBOUR)
       self.app.rednode.add(resource(uri), CONNECTED, NO)

  </red:module>
</red:code>


