# OWL Product  a basic python product
#
# by Josef Meile <jmeile@hotmail.com>
#
# This software is governed by a license. See
# LICENSE.txt for the terms of this license.

#Documenting string
__doc__="""OWL product module."""
#Release number
__version__='0.1'

#Setups security declarations
from Globals import InitializeClass

#Provides a callable object wrapped around a ZPT
from Products.PageTemplates.PageTemplateFile import PageTemplateFile

#Allows you to define the security permissions of your
#class methods
from AccessControl import ClassSecurityInfo

#Some predefined permissions to protect your information
#view: protects your information of being viewed
#access_contents_information: protects your content properties
#like size, id, date, etc. Currently, it's not used here
#from AccessControl.Permissions import view, access_contents_information

#Basic functionality to make your product work in the
#ZODB (Subclases from Globals.Persistent, Acquisition.Implicit,
#and AccessControl.Role.RoleManager)
from OFS.SimpleItem import SimpleItem

#With this class you can define some properties that you can
#edit thru the manage interface. You can also create or delete
#properties
from OFS.PropertyManager import PropertyManager

#Quotes html
from urllib import quote

#Some ZPT Macros for the management views
from Products.JMUtils.JMZPTMacros import JMZPTMacros
from OKeyParser import ParseXmlOKey





OwlRelations = {}
OwlKeys = {}
Ontology = {}
    

#Edit permission of the class (it can be whatever you want, but
#I took 'Change MyClassName' + 's' because it's the standard that
#zope uses
EDIT_PERM='Change OWL'

#loads my default add form
_addOWLForm=PageTemplateFile('zpt/OWL_Add',globals())


def OWLinit():
  global OwlRelations
  global OwlKeys
  global Ontology
  
  [OwlRelations, OwlKeys, Ontology] = ParseXmlOKey() 
  
  
#The Kind attribute is passed to the page template
def manage_addOWLForm(self):
  """Here some attributes are added to the template"""

  #This is necesary in order to allow other users to access to this template
  _addOWLForm._owner=None

  #Adds the Kind attribute to the built-in variable "options"
  return _addOWLForm.__of__(self)(Kind='OWL')

#Before starting with the method definition, you have
#to know that you always need to include a doc string
#inmediately after the method definition; otherwise,
#zope will raise an error when you try to use the
#method. A doc string is always enclosed by trhee
#double qoutes

def manage_addOWL(self,id,title='',description='',REQUEST=None,submit=None):
  """Invoques the __init__ method of the OWL class"""
  #I don't want spaces in my ids, so I replace them with
  #an underscore. If you're in Switzerland for example,
  #you may also want to replace the Umlauts. This is better
  #done with the "re" module of python
  id=id.replace(' ','_')

  #Calls the OWL constructor
  boringObj=OWL(id,title,description)

  #Associates the boringObj with the given id
  self._setObject(id,boringObj)

  #If there is a REQUEST object, then you'll be redirected
  #to the proper management view; Otherwise, it means that
  #you called it programmatically and not from the manage
  #interface
  if REQUEST is not None:

    #I don't know if I really need this part, but that's is
    #how it's done in "addDTMLMethod" of
    #<zope-root>/lib/python/OFS/DTMLMethod.py
    try:
      destURL=self.DestinationURL()
    except:
      destURL=REQUEST['URL1']

    if submit==" Add and Edit ":
      #destURL is the manage_main screen of the created
      #object
      destURL="%s/%s" % (destURL,quote(id))
    #if summit!=" Add and Edit ", then destURL is the manage_main
    #view of the container folder
    REQUEST.RESPONSE.redirect(destURL+'/manage_main')
  return ''

#Here I include the subclasses of my OWL product
#See the import comments to know what does each class
class OWL(SimpleItem, PropertyManager, JMZPTMacros):
  """OWL class definition"""

  global OwlRelations
  global OwlKeys
  global Ontology
  
  #defines the security access policies of your methods
  security=ClassSecurityInfo()

  #This is what appears in product add list of the ZMI
  #Make sure it's unique, for it's also used by the
  #ZCatalog
  meta_type='OWL'

  #Here you define the manage tabs by giving a name, the method
  #you want to excecute after the tab is pressed, and an
  #associated help file. Please note that common views like
  #Security, Undo, Ownership, and find are already included in
  #SimpleItem
  manage_options=(
    (
        #Each manage tab consist of:
        #'label': The text that you'll see on the management interface
        #'action': Form or method that will be excecuted when you click on it
        #'help': Name of the product + name of the help file for this view
        {'label':'Edit',
         'action':'manage_main',
         'help':('OWL','OWL_Edit.stx')
        },
        {'label':'View',
         'action':'manage_view',
         'help':('OWL','OWL_View.stx')
        },
        {'label':'Properties',
         'action':'manage_propertiesForm',
         'help':('OWL','OWL_Properties.stx')
        }
    )
    #You can delete the last element and uncomment the
    #following line, if you want to see the default sytem
    #help for the Properties view
    #+PropertyManager.manage_options
    +SimpleItem.manage_options
  )

  #Here you define the properties that you want to change
  #thru the management interface
  #mode, if included, can be:
  #'r': read only
  #'w': writable
  #'d': deletable
  #Or a mix of them (By default a property is writable and
  #deletable)

  _properties=({'id':'title','type':'string','mode':'r'},
               {'id':'description','type':'text','mode':'w'},
               {'id':'cols','type':'int','mode':'w'},
               {'id':'rows','type':'int','mode':'w'}
              )

  def __init__(self,id,title='',description='',cols=0,rows=0):
    """Contructor method to initialize the properties of our class"""
    #Create and initilize the class attributes
    self.id=id
    self.title=title
    self.description=description

    #Some unnecesary properties to ilustrate how Property manager works
    self.cols=cols
    self.rows=rows

  #Specifies the location of the page template for editing
  #the attributes of the class
  manage_main=PageTemplateFile('zpt/OWL_Edit',globals())
  #This is necesary in order to allow other users to access to this template
  manage_main._owner=None

  #Only users with the 'Change OWLs' permission can use this method 
  security.declareProtected(EDIT_PERM,'manage_edit')
  def manage_edit(self,title,description,REQUEST=None):
    """Edits a OWL class instance"""
    #Changes the attribute values
    self.title=title
    self.description=description
    #If it was called from the manage interface, you'll be redirected
    #to the manage_main view of this object and you'll see a message
    #which indicates that the properties were changed
    if REQUEST is not None:
      msg="%s was updated." % self.id
      return self.manage_main(self,REQUEST,manage_tabs_message=msg)

  #Specifies the location of the manage_view page template
  manage_view=PageTemplateFile('zpt/OWL_View',globals())
  #This is necesary in order to allow other users to access to this template
  manage_view._owner=None

  #Specifies the location of the default view page template
  index_html=PageTemplateFile('zpt/index_html',globals())
  #This is necesary in order to allow other users to access to this template
  index_html._owner=None

  #Remove this comments if you add and/or delete class attributes, then
  #restart zope. You have to know that old instances of your class will
  #be only updated when they become active. If you want to change them
  #at once, then you will have to write a method that retreives all the
  #old instances, add a default value for your new attributes, and
  #delete the depracated ones
  #def __setstate__(self,state):
  #  """This method adds new attributes and deletes old ones each time
  #  that you view old instances of the class"""
  #  #If you inherit directly from Persistent and you don't use
  #  #SimpleItem, then you have to uncomment the first line and comment
  #  #the second one
  #  #Persistent.__setstate__(self,state)
  #  SimpleItem.__setstate__(self,state)
  #  #here you have to replace newAttr with the name of the
  #  #new attribute
  #  if not hasattr(self,'newAttr'):
  #    #Give a default value
  #    self.newAttr='this is newAttr'
  #  #here you have to replace deprecatedAttr with the name of the
  #  #old attribute
  #  if hasattr(self,'deprecatedAttr'):
  #    del self.deprecatedAttr

  
  def getKeyName( self, key='' ):
    """ full list Ontology """
    return OwlKeys.get(key)

  def getOwlRelationsList(self):
    """ full list Ontology relatins """
    return OwlRelations
    
  def getRelationScore( self, key='' ):
    """ full list Ontology """
    return OwlRelations.get(key)

  def getRelatedTo(self, key='', relation='' ):
    """ related of """
    res = []
    if Ontology.has_key(key):
      tmp = Ontology[key]
      if tmp.has_key(relation):
        res = tmp[relation]
    return res

  def getOwlKey(self, key=''):
    """ related of """
    if Ontology.has_key(key):
      return Ontology[key]
    return None
  
  def getOwlList(self):
    """ full list Ontology """
    return OwlKeys

  
  
  def searchOwlKeys(self, pattern='', count=5, step=0, search_type=0 ):
    """ search keywords """
    res = []
    
    try:
      step=int(step)
    except:
      step=0
    
    try:
      count=int(count)
    except:
      count=5
    
    try:
      search_type=int(search_type)
    except:
      search_type=0
    
    if pattern == None:
      return 0, res
    
    if search_type == 1:
      if Ontology.has_key(pattern):
        res.append(pattern)
      return len(res), res
    
    for i in OwlKeys:
      if pattern in OwlKeys.get(i):
        res.append(i)
    return len(res), res[(step*count):((step+1)*count)]

    
    
    
    
#Initializes your class and set ups the security declarations
InitializeClass(OWL)
