Source code for ximpia.xpcore.business

# coding: utf-8

# python
import types
import datetime
import random
import os
import copy

from django.contrib.auth.models import User, Group as GroupSys
from django.utils.translation import ugettext as _

from models import XpMsgException, XpRegisterException, get_blank_wf_data
from models import View, Action, Application, ViewParamValue, Param, Workflow, WFParamValue, WorkflowView, ViewMenu, Menu, MenuParam, \
	SearchIndex, SearchIndexParam, SearchIndexWord, Word, XpTemplate, ViewTmpl, WorkflowData, ApplicationMeta, ApplicationTag, Service, \
	Condition, ViewMenuCondition, ServiceMenuCondition
from ximpia.xpsite.models import Category, Tag, Group
from ximpia.util import resources
from models import CoreParam
import constants as K

# Settings
from ximpia.xpcore.util import get_class, get_instances, get_app_name
from ximpia.xpcore.models import MetaKey, ServiceMenu
settings = get_class(os.getenv("DJANGO_SETTINGS_MODULE"))

# Logging
import logging.config
logging.config.dictConfig(settings.LOGGING)
logger = logging.getLogger(__name__)

from data import WorkflowDataDAO, WorkflowDAO, WFParamValueDAO, ParamDAO, ViewDAO, WorkflowViewDAO
from models import Context, JsResultDict
from choices import Choices

from ximpia.util.js import Form as _jsf

class AppCompRegCommonBusiness ( object ):
	_ctx = None
	def __init__(self, compName, ctx=None, doClean=False):
		"""Parent class for application component registering."""
		self._ctx = ctx
		appName = self.__getAppName(compName)
		self._reg = ComponentRegisterBusiness()
		if appName != None and doClean == True:
			self._reg.cleanAll(appName)
		self.views()
		self.templates()
		self.actions()
		self.flows()
		self.menus()
		self.viewMenus()
		self.search()
	def __getAppName(self, compName):
		return get_app_name('.'.join(compName.split('.')[:2]))
	def views(self):
		"""Doc."""
		pass
	def templates(self):
		"""Doc."""
		pass
	def actions(self):
		"""Doc."""
		pass
	def flows(self):
		"""Doc."""
		pass
	def menus(self):
		"""Doc."""
		pass
	def viewMenus(self):
		"""Doc."""
		pass
	def search(self):
		pass

class ComponentRegisterBusiness ( object ):	
	
	def __init__(self):
		pass
	
	def __getAppName(self, compName):
		return get_app_name('.'.join(compName.split('.')[:2]))
	
	def registerApp(self, compName, title=None, slug='', **args):
		"""
		
		Register application
		
		**Required Attributes**
		
		* ``compName``:StringType : Component name, __name__ from components module
		* ``title``:StringType : Application title
		* ``slug``:StringType : Application slug to show in urls 
		
		**Optional Attributes**
		
		* ``isAdmin``:BooleanType : Application is admin type
		* ``isSubscription``
		* ``isPrivate``
		* ``isAdmin``
		* ``developer``
		* ``developerOrg``
		* ``parentSlug``
		* ``meta``
		* ``category``:StringType
		* ``tags``:ListType
		
		**Returns**
		
		None
		
		"""
		if title == None or slug == '':
			raise XpRegisterException(AttributeError, 'registerApp requires title and slug attributes')
		logger.debug('compName: {}'.format(compName))
		name = self.__getAppName(compName)
		logger.debug('name: {}'.format(name))
		# Create group application if not exists
		logger.debug('registerApp :: slug: %s' % (slug) )
		category = Category.objects.get(name='Apps')
		logger.debug('registerApp :: category: %s' % (category) )
		groupSys, exists = GroupSys.objects.get_or_create(name=slug) #@UnusedVariable
		group, exists = Group.objects.get_or_create(group=groupSys, groupNameId=slug, category=category)
		try:
			app = Application.objects.get(name=name)
		except Application.DoesNotExist:
			app = Application(name=name, slug=slug) 
		app.title = title
		app.accessGroup = group
		# Optional data
		if args.has_key('isSubscription'):
			app.isSubscription = args['isSubscription']
		if args.has_key('isPrivate'):
			app.isPrivate = args['isPrivate']
		if args.has_key('isAdmin'):
			app.isAdmin = args['isAdmin']
		if args.has_key('developer'):
			app.developer = User.objects.get(username=args['developer'])
		if args.has_key('developerOrg'):
			app.developerOrg = Group.objects.get(name=args['developerOrg'])
		if args.has_key('parentSlug'):
			app.parent = Application.objects.get(slug=args['parentSlug'])
		if args.has_key('category'):
			app.category = Category.objects.get(name=args['category'])
		app.save()
		# Meta
		if args.has_key('meta'):
			# get meta keys
			metaKeys = MetaKey.objects.filter(name__in=args['meta'].keys())
			for metaKey in args['meta']:
				try:
					appMeta = ApplicationMeta.objects.get(application=app, meta=metaKeys.get(name=metaKey))
				except ApplicationMeta.DoesNotExist:
					ApplicationMeta.objects.create(application=app, meta=metaKeys.get(name=metaKey), value=args['meta'][metaKey])
		# Tags
		if args.has_key('tags'):
			tags = Tag.objects.filter(name__in=[args['tags']])
			for tag in tags:
				try:
					appTag = ApplicationTag.objects.get(application=app, tag=tags.filter(name=tag.name))
				except ApplicationTag.DoesNotExist:
					ApplicationTag.objects.create(application=app, tag=tags.filter(name=tag.name))
		logger.info( 'Registered application: %s' % (app) )
	
	def registerService(self, compName, serviceName=None, className=None):
		"""
		
		Register service
		
		**Required Attributes**
		
		* ``compName``
		* ``serviceName``
		* ``className``
		
		**Optional Attributes**
		
		**Returns**
		
		"""
		if serviceName == None or className == None:
			raise XpRegisterException(AttributeError, 'registerService requires serviceName and className')
		appName = self.__getAppName(compName)
		classPath = str(className).split("'")[1]
		app = Application.objects.get(name=appName)
		impl = classPath
		try:
			service = Service.objects.get(application=app, name=serviceName)
			service.implementation = impl
			service.save()
		except Service.DoesNotExist:
			Service.objects.create(application=app, implementation=impl, name=serviceName)
		logger.info( 'Registered service %s' % (serviceName) )
	
	def cleanAll(self, compName):
		"""
		
		Clean views, actions, workflows, menus, search and templates for application
		
		**Attributes**
		
		* ``compName`` : __name__ from components module. From this value we get the application name
		
		"""
		
		appName = self.__getAppName(compName)
		Application.objects.filter(name=appName).update(isDeleted=True)
		logger.info( 'deleted application %s' % appName )
		#View.objects.filter(application__name=appName).delete()
		#logger.info( 'deleted all views for %s' % appName )
		#Action.objects.filter(application__name=appName).delete()
		#logger.info( 'deleted all actions for %s' % appName )
		#Workflow.objects.filter(application__name=appName).delete()
		#WorkflowData.objects.filter(flow__application__name=appName).delete()
		#logger.info( 'deleted all flows for %s' % appName )
		#Menu.objects.filter(application__name=appName).delete()
		#logger.info( 'deleted all menus for %s' % appName )
		#XpTemplate.objects.filter(application__name=appName).delete()
		#logger.info( 'deleted all templates for %s' % appName )
	
	def registerServMenu(self, compName, serviceName=None, menus=[]):
		"""
		
		Register application menus for zone main and sys. Application menus will be shown for all views in an application
		
		**Required Attributes**
		
		* ``compName``
		* ``serviceName``
		* ``menus``
		
		**Optional Attributes**
		
		**Returns**
		
		None
		
		"""
		if len(menus) == 0 or serviceName == None:
			raise XpRegisterException(AttributeError, 'registerServMenu requires attributes serviceName and menus')
		appName = self.__getAppName(compName)
		app = Application.objects.get(name=appName)
		service = Service.objects.get(name=serviceName, application=app) #@UnusedVariable
		# Menu
		#ServiceMenu.objects.filter(service=service).delete()
		groupDict = {}
		singleList = []
		counterDict = {}
		for dd in menus:
			if dd.has_key(K.GROUP):
				if not groupDict.has_key(dd[K.GROUP]):
					groupDict[dd[K.GROUP]] = []
				groupDict[dd[K.GROUP]].append(dd)
			else:
				singleList.append(dd)
		# Single Menus - Not Grouped
		counter = 100
		for dd in singleList:
			if not dd.has_key(K.ZONE):
				dd[K.ZONE] = K.VIEW
			try:
				menu = Menu.objects.get(name=dd[K.MENU_NAME])
				sep = dd[K.SEP] if dd.has_key(K.SEP) else False
				logger.debug( 'counter: %s' % (counter) )
				try:
					serviceMenu = ServiceMenu.objects.get(service=service, menu=menu)
				except ServiceMenu.DoesNotExist:
					serviceMenu = ServiceMenu(service=service, menu=menu)
				serviceMenu.hasSeparator = sep
				serviceMenu.zone=dd[K.ZONE]
				serviceMenu.order = counter
				serviceMenu.save()
				# conditions
				if K.CONDITIONS in dd:
					order = 10
					for name, action, value in map(lambda x: x.split(':'), dd[K.CONDITIONS].split(',')):
						condition = Condition.objects.get(name=name)
						ServiceMenuCondition.objects.create(serviceMenu=serviceMenu, condition=condition, action=action, value=value, 
														order=order)
						order += 10
				counterDict[dd[K.MENU_NAME]] = counter
				counter += 100
			except Menu.DoesNotExist:
				pass
		# Grouped Menus
		for groupName in groupDict:
			fields = groupDict[groupName]
			menuParent = Menu.objects.get(name=groupName)
			serviceMenuParent = ServiceMenu.objects.get(service=service, menu=menuParent)
			counter = serviceMenuParent.order + 10
			for dd in fields:
				if not dd.has_key(K.ZONE):
					dd[K.ZONE] = K.VIEW
				menu = Menu.objects.get(name=dd[K.MENU_NAME])
				sep = dd[K.SEP] if dd.has_key(K.SEP) else False
				#logger.debug( 'data: %s' % (view.name, menuParent.name, menu.name, sep, dd[K.ZONE], counter) )
				logger.debug( 'data: %s' % ( counter) )
				try:
					serviceMenu = ServiceMenu.objects.get(service=service, menu=menu)
				except ServiceMenu.DoesNotExist:
					serviceMenu = ServiceMenu(service=service, menu=menu)
				serviceMenu.hasSeparator = sep
				serviceMenu.zone=dd[K.ZONE]
				serviceMenu.order = counter
				serviceMenu.parent = serviceMenuParent
				serviceMenu.save()
				# conditions
				if K.CONDITIONS in dd:
					order = 10
					for name, action, value in map(lambda x: x.split(':'), dd[K.CONDITIONS].split(',')):
						condition = Condition.objects.get(name=name)
						ServiceMenuCondition.objects.create(serviceMenu=serviceMenu, condition=condition, action=action, value=value, 
														order=order)
						order += 10
				counter += 10
		logger.info( 'Registered menus for service %s' % (serviceName) )

	def registerCondition(self, compName, condition, rule):
		"""
		Register condition
		
		** Required Attributes **
		
		* ``compName``
		* ``condition``
		* ``rule``
		"""
		Condition.objects.get_or_create(name=condition, rule=rule)
		logger.info( 'Registered condition {}'.format(condition))

	def registerViewMenu(self, compName, viewName=None, menus=[]):
		"""
		
		Register views associated with a menu
		
		**Required Attributes**
		
		* ``compName``
		* ``viewName``
		* ``menus``: [zone, group, menu_name, conditions]

		**Optional Attributes**

		**Returns**

		None

		"""
		logger.info( 'register view Menus...' )
		if viewName == None or len(menus) == 0:
			raise XpRegisterException(AttributeError, 'registerViewMenu requires attributes viewName and menus')
		appName = self.__getAppName(compName)
		app = Application.objects.get(name=appName)
		view = View.objects.get(application=app, name=viewName)
		# Menu
		logger.info( 'View menus...' )
		ViewMenu.objects.filter(view=view).delete()
		groupDict = {}
		singleList = []
		counterDict = {}
		for dd in menus:
			if dd.has_key(K.GROUP):
				if not groupDict.has_key(dd[K.GROUP]):
					groupDict[dd[K.GROUP]] = []
				groupDict[dd[K.GROUP]].append(dd)
			else:
				singleList.append(dd)
		# Single Menus - Not Grouped
		counter = 100
		for dd in singleList:
			if not dd.has_key(K.ZONE):
				dd[K.ZONE] = K.VIEW
			try:
				menu = Menu.objects.get(name=dd[K.MENU_NAME])
				sep = dd[K.SEP] if dd.has_key(K.SEP) else False
				#logger.info( 'data: %s' % (view.name, menu.name, sep, dd[K.ZONE], counter) )
				logger.info( 'data: %s' % (counter) )
				try:
					viewMenu = ViewMenu.objects.get(view=view, menu=menu)
				except ViewMenu.DoesNotExist:
					viewMenu = ViewMenu(view=view, menu=menu)
				viewMenu.hasSeparator = sep
				viewMenu.zone=dd[K.ZONE]
				viewMenu.order = counter
				viewMenu.save()
				# conditions
				if K.CONDITIONS in dd:
					order = 10
					for name, action, value in map(lambda x: x.split(':'), dd[K.CONDITIONS].split(',')):
						condition = Condition.objects.get(name=name)
						ViewMenuCondition.objects.create(viewMenu=viewMenu, condition=condition, action=action, value=value, 
														order=order)
						order += 10
				counterDict[dd[K.MENU_NAME]] = counter
				counter += 100
			except Menu.DoesNotExist:
				pass
		# Grouped Menus
		for groupName in groupDict:
			fields = groupDict[groupName]
			menuParent = Menu.objects.get(name=groupName)
			viewMenuParent = ViewMenu.objects.get(view=view, menu=menuParent)
			counter = viewMenuParent.order + 10
			for dd in fields:
				if not dd.has_key(K.ZONE):
					dd[K.ZONE] = K.VIEW
				menu = Menu.objects.get(name=dd[K.MENU_NAME])
				sep = dd[K.SEP] if dd.has_key(K.SEP) else False
				#logger.info( 'data: %s' % (view.name, menuParent.name, menu.name, sep, dd[K.ZONE], counter) )
				logger.info( 'data: %s' % ( counter) )
				try:
					viewMenu = ViewMenu.objects.get(view=view, menu=menu)
				except ViewMenu.DoesNotExist:
					viewMenu = ViewMenu(view=view, menu=menu)
				viewMenu.hasSeparator = sep
				viewMenu.zone=dd[K.ZONE]
				viewMenu.order = counter
				viewMenu.parent=viewMenuParent
				viewMenu.save()
				# conditions
				if K.CONDITIONS in dd:
					order = 10
					for name, action, value in map(lambda x: x.split(':'), dd[K.CONDITIONS].split(',')):
						condition = Condition.objects.get(name=name)
						ViewMenuCondition.objects.create(viewMenu=viewMenu, condition=condition, action=action, value=value, 
														order=order)
						order += 10
				counter += 10
		logger.info( 'Registered menus for view %s' % (viewName) )
	
	def cleanViews(self, compName):
		"""Clean all views for application."""
		appName = self.__getAppName(compName)
		View.objects.filter(application__name=appName).update(isDeleted=True)
		logger.info( 'deleted all views for %s' % appName )
	
	def registerView(self, compName, serviceName=None, viewName=None, className=None, method=None, winType=Choices.WIN_TYPE_WINDOW, 
				hasAuth=False, slug='', **args):
		"""Registers view
		
		**Required Attributes**
		
		* ``compName``
		* ``serviceName``
		* ``viewName``
		* ``className``
		* ``method``
		* ``winType``
		* ``hasUrl``
		* ``hasAuth``
		* ``slug``
		
		**Optional Attributes**
		
		* ``params``:DictType : View entry parameters entry by **args:DictType Having format name => [value1, value2, ...]
		* ``image``
		* ``meta``
		* ``category``
		* ``tags``
		
		**Returns**
		
		None
		
		"""		
		if viewName == None or className == None or method == None or slug == '':
			raise XpRegisterException(AttributeError, 'registerView requires viewName, className, method and slug attributes')
		appName = self.__getAppName(compName)
		# from impl take myClass and method
		# '.'.join(compName.split('.')[:2])
		classPath = str(className).split("'")[1]
		app = Application.objects.get(name=appName)
		service = Service.objects.get(name=serviceName, application=app)
		try:
			view = View.objects.get(application=app, service=service, name=viewName)
		except View.DoesNotExist:
			view = View(application=app, service=service, name=viewName)
		view.implementation = classPath + '.' + method
		view.winType = winType
		view.hasAuth = hasAuth
		view.slug = slug
		view.save()
		# Parameters
		for name in args:
			param = Param.objects.get(application=app, name=name)
			fields = args[name]
			for value in fields:
				theTuple = ViewParamValue.objects.get_or_create(view=view, name=param, operator='eq', value=value) #@UnusedVariable
		logger.info( 'Registered view %s' % (viewName) )
	
	def cleanActions(self, compName):
		"""Clean all actions for application.
		@param appCode: Application code"""
		appName = self.__getAppName(compName)
		Action.objects.filter(application__name=appName).update(isDeleted=True)
		logger.info( 'deleted all actions for %s' % appName )
	
	def registerAction(self, compName, serviceName=None, actionName=None, className=None, method=None, slug=None, **args):
		"""Registers action
		
		**Required Attributes**
		
		* ``compName``
		* ``serviceName``
		* ``actionName``
		* ``slug``
		* ``className``
		* ``method``
		
		**Optional Attributes**
		
		* ``hasAuth``
		
		**Returns**
		
		None
		"""
		if actionName == None or className == None or method == None or slug == None:
			raise XpRegisterException(AttributeError, 'registerAction requires actionName, slug, className and method attributes')
		appName = self.__getAppName(compName)
		classPath = str(className).split("'")[1]
		app = Application.objects.get(name=appName)
		service = Service.objects.get(name=serviceName, application=app)
		try:
			action = Action.objects.get(application=app, name=actionName, service=service)
		except Action.DoesNotExist:
			action = Action(application=app, name=actionName, service=service)
		action.slug = slug
		action.implementation = classPath + '.' + method
		if args.has_key('hasAuth'):
			action.hasAuth = args['hasAuth']
		action.save()
		logger.info('Registered action %s' % (actionName) )
	
	def registerParam(self, compName, name=None, title=None, paramType=None, isView=False, isWorkflow=False):
		"""Register view / workflow parameter
		
		**Required Attributes**
		
		* ``compName``
		* ``name``
		* ``title``
		* ``paramType``
		* ``isView``
		* ``isWorkflow``
		
		**Optional Attributes**
		
		**Returns**
		
		None
		
		"""
		if name == None or title == None or paramType == None:
			raise XpRegisterException(AttributeError, 'registerParam requires attributes name, title and paramType')
		appName = self.__getAppName(compName)
		app = Application.objects.get(name=appName)
		try:
			param = Param.objects.get(application=app, name=name)
		except Param.DoesNotExist:
			param = Param(application=app, name=name)
		param.title = title
		param.paramType=paramType
		param.view = isView
		param.workflow = isWorkflow
		param.save()
	
	def cleanFlows(self, compName):
		"""Clean all flows for application."""
		appName = self.__getAppName(compName)
		Workflow.objects.filter(application__name=appName).update(isDeleted=True)
		WorkflowData.objects.filter(flow__application__name=appName).update(isDeleted=True)
		logger.info( 'deleted all flows for %s' % appName )
	
	def registerFlow(self, compName, flowCode=None, resetStart=False, deleteOnEnd=False, jumpToView=True):
		"""
		Reister flow
		
		**Required Attributes**
		
		* ``flowCode``
		
		**Optional Attributes**
		
		* ``resetStart``
		* ``deleteOnEnd``
		* ``jumoToView``
		
		**Returns**
		
		None
		
		"""
		if flowCode == None:
			raise XpRegisterException(AttributeError, 'registerFlow requires flowCode')
		appName = self.__getAppName(compName)
		app = Application.objects.get(name=appName)
		try:
			flow = Workflow.objects.get(application=app, code=flowCode)
		except Workflow.DoesNotExist:
			flow = Workflow(application=app, code=flowCode)		
		flow.resetStart = resetStart
		flow.deleteOnEnd = deleteOnEnd
		flow.jumpToView = jumpToView
		flow.save()
		
	def registerFlowView(self, compName, flowCode=None, viewNameTarget=None, actionName=None, order=10, **args):
		"""
		Reister flow
		
		**Required Attributes**
		
		* ``flowCode``
		* ``viewNameTarget``
		* ``actionName``
		* ``order`` : Order to evaluate view target resolution
		
		**Optional Attributes**
		
		* ``params`` : Workflow parameters. Dictionary that contains the parameters to resolve views. Has the format name => (operator, value)
		* ``viewParams`` : View entry parameters
		* ``viewNameSource`` 
		
		**Returns**
		
		None
		
		"""
		if flowCode == None or viewNameTarget == None or actionName == None:
			raise XpRegisterException(AttributeError, """registerFlowView requires attributes flowCode, viewNameTarget,
															and actionName""")
		appName = self.__getAppName(compName)
		app = Application.objects.get(name=appName)
		
		viewTarget = View.objects.get(application=app, name=viewNameTarget)
		action = Action.objects.get(application=app, name=actionName)
		flow = Workflow.objects.get(code=flowCode)
		try:
			flow = WorkflowView.objects.get(flow=flow, viewTarget=viewTarget, action=action)
		except WorkflowView.DoesNotExist:
			flow = WorkflowView(flow=flow, viewTarget=viewTarget, action=action)
		if args.has_key('viewNameSource'):
			viewSource = View.objects.get(application=app, name=args['viewNameSource'])
			flow.viewSource = viewSource
		flow.order = order
		flow.save()		
		# Parameters
		if args.has_key('params'):
			for name in args['params']:
				operator, value = args['params'][name]
				wfParamValue, created = WFParamValue.objects.get_or_create(flow=flow, name=name, operator=operator, value=value) #@UnusedVariable
		# Entry View parameters
		# TODO: Complete entry view parameters
	
	def cleanMenu(self, compName):
		"""
		Clean all menus for application
		
		**Attributes**
		
		* ``compName``
		
		**Returns**
		
		None
		"""
		appName = self.__getAppName(compName)
		Menu.objects.filter(application__name=appName).update(isDeleted=True)
		logger.info( 'deleted all menus for %s' % appName )
	
	def registerMenu(self, compName, name='', **args):
		"""Register menu item
		
		**Required Attributes**
		
		* ``compName``
		* ``name``
		
		**Optional Attributes**
		
		* ``title``
		* ``iconName``
		* ``description``
		* ``actionName`` : Either actionName or viewName must be informed
		* ``viewName`` : Either actionName or viewName must be informed
		* ``url``
		* ``urlTarget``
		* ``params``:DictType
		
		**Returns**
		
		None
		"""
		if name == '':
			raise XpRegisterException(AttributeError, 'registerMenu requires attributes name')
		if not args.has_key('viewName') and not args.has_key('actionName'):
			raise XpRegisterException(AttributeError, """registerMenu requires menu items be lined to a view or action. Need to inform 
					either one.""")
		if not args.has_key('title') and not args.has_key('icon'):
			raise XpRegisterException(AttributeError, 'registerMenu needs either text or icon')
		appName = self.__getAppName(compName)
		app = Application.objects.get(name=appName)
		# Icon
		if args.has_key('iconName'):
			icon, created = CoreParam.objects.get_or_create(mode=K.PARAM_ICON, name=args['iconName'], value=args['iconName']) #@UnusedVariable
		# Menu
		try:
			menu = Menu.objects.get(name=name)
		except Menu.DoesNotExist:
			menu = Menu(	application=app,
							name=name
							)
			if args.has_key('title'):
				menu.title = args['title']
			if args.has_key('description'):
				menu.description = args['description']
			if args.has_key('iconName'):
				menu.icon = icon
		if args.has_key('url'):
			menu.url = args['url']
			menu.urlTarget = args['urlTarget']
		if args.has_key('actionName'):
			action = Action.objects.get(name=args['actionName'])
			menu.action = action
		if args.has_key('viewName'):
			view = View.objects.get(application__name=appName, name=args['viewName'])
			menu.view = view
		menu.save()
		# MenuParam
		if args.has_key('params'):
			for name in args['params']:
				operator, value = args['params'][name]
				menuValue, created = MenuParam.objects.get_or_create(menu=menu, name=name, operator=operator, value=value) #@UnusedVariable
	
	def registerSearch(self, compName, text='', viewName=None, actionName=None, **args):
		"""
		Register application operation. It will be used in view search.
		
		**Required Attributes**
		
		* ``compName``
		* ``text``
		* ``viewName``
		* ``actionName``
		
		**Optional Attributes**
		
		* ``params``
		
		**Returns**
		
		None
		"""
		if viewName == None and actionName == None:
			raise XpRegisterException(AttributeError, 'registerSearch requires either viewName or actionName')
		if text == '' or (viewName == None and actionName == None):
			raise XpRegisterException(AttributeError, 'registerSearch requires attributes text, viewName or actionName. ')
		appName = self.__getAppName(compName)
		wordList = resources.Index.parseText(text)
		logger.info( 'wordList: %s' % wordList )
		view = View.objects.get(name=viewName) if viewName != None else None
		action = Action.objects.get(name=actionName) if actionName != None else None
		app = Application.objects.get(name=appName)
		# Create search index
		try:
			search = SearchIndex.objects.get(application=app, title=text)
		except SearchIndex.DoesNotExist:
			search = SearchIndex(application=app, title=text)
		if view != None:
			search.view = view
		if action != None:
			search.action = action
		search.save()
		# delete all words for search in SearchIndexWord
		SearchIndexWord.objects.filter(index=search, word__word__in=wordList).delete()
		for wordName in wordList:
			# Word
			word, created = Word.objects.get_or_create(word=wordName) #@UnusedVariable
			# SearchIndexWord
			try:
				searchWord = SearchIndexWord.objects.get(word=word, index=search)
			except SearchIndexWord.DoesNotExist:
				searchWord = SearchIndexWord.objects.create(word=word, index=search) #@UnusedVariable
		if args.has_key('params'):
			for paramName in args['params']:
				param = Param.objects.get_or_create(application=app, name=paramName)
				indexParam = SearchIndexParam.objects.create(searchIndex=search, name=param, operator=Choices.OP_EQ, #@UnusedVariable
									value=args['params'][paramName])
	
	def cleanTemplates(self, compName):
		"""Clean templates for the application
		@param appCode: Application code"""
		appName = self.__getAppName(compName)
		XpTemplate.objects.filter(application__name=appName).update(isDeleted=True)
		logger.info( 'deleted all templates for %s' % appName )
	
	def registerTemplate(self, compName, viewName=None, name=None, **args):
		"""Register template
		
		**Required Attributes**
		
		* ``compName``
		* ``viewName``
		* ``name``
		
		**Optional Attributes**
		
		* ``language``
		* ``country``
		* ``winType``
		* ``device``
		* ``alias``
		
		**Returns**
		
		None
		"""
		if viewName == None or name == None:
			raise XpRegisterException(AttributeError, 'registerTemplate requires viewName and template name attributes')
		appName = self.__getAppName(compName)
		app = Application.objects.get(name=appName)
		view = View.objects.get(application=app, name=viewName) if viewName != None else None
		try:
			template = XpTemplate.objects.get(name=name)
		except XpTemplate.DoesNotExist:
			template = XpTemplate(application=app, name=name)
		if args.has_key('language'):
			template.language = args['language']
		if args.has_key('country'):
			template.country = args['country']
		if args.has_key('winType'):
			template.winType = args['winType']
		if args.has_key('device'):
			template.device = args['device']
		if args.has_key('alias'):
			template.alias = args['alias']
		else:
			template.alias = viewName		
		template.save()
		# View
		try:
			viewTmpl = ViewTmpl.objects.get(view=view, template=template)
		except ViewTmpl.DoesNotExist:
			ViewTmpl.objects.create(view=view, template=template)
		logger.info('Registered template %s for view %s' % (name, viewName) )
	
[docs]class WorkFlowBusiness (object): _ctx = {} __wfData = {} def __init__(self, ctx): self._ctx = ctx self._dbWFData = WorkflowDataDAO(ctx, related_depth=2) self._dbWorkflow = WorkflowDAO(ctx, related_depth=2) self._dbWFView = WorkflowViewDAO(ctx, related_depth=2) self._dbWFParams = WFParamValueDAO(ctx, related_depth=2) self._dbView = ViewDAO(ctx) self._dbParam = ParamDAO(ctx) #self._dbWFViewParam = WFViewEntryParamDAO(ctx, related_depth=2) self.__wfData = get_blank_wf_data({})
[docs] def gen_user_id(self): """Generate workflow user id. ** Returns ** user_id """ user_id = '' while len(user_id) < 40: user_id += random.choice('0123456789abcde') return user_id
[docs] def get(self, flow_code): """Get flow.""" flow = self._dbWorkflow.get(code=flow_code) return flow
[docs] def resolve_flow_data_for_user(self, wf_user_id, flow_code): """Resolves flow for user and session key. @param wf_user_id: Workflow User Id @param flow_code: Flow code @return: resolved_flow : Resolved flow for flow code , login user or session""" resolvedFlow = None flows = self._dbWFData.search(flow__code=flow_code, userId=wf_user_id) logger.debug( 'flows: %s' % (flows) ) logger.debug( 'All: %s' % (self._dbWFData.getAll()) ) if len(flows) > 0: resolvedFlow = flows[0] else: raise XpMsgException(None, _('Error in resolving workflow for user')) logger.debug( 'resolvedFlow: %s' % (resolvedFlow) ) return resolvedFlow
[docs] def resolve_view(self, wf_user_id, app_name, flow_code, view_name_source, action_name): """Search destiny views with origin viewSource and operation actionName @param view_name_source: Origin view @param action_name: Action name @return: view_target""" viewTarget = '' flowViews = self._dbWFView.search(flow__application__name=app_name, flow__code=flow_code, viewSource__name=view_name_source, action__name=action_name).order_by('order') params = self._dbWFParams.search(flowView__in=flowViews) paramFlowDict = {} for param in params: if not paramFlowDict.has_key(param.flowView.flow.code): paramFlowDict[param.flowView.flow.code] = [] paramFlowDict[param.flowView.flow.code].append(param) wfDict = self.getFlowDataDict(wf_user_id, flow_code) logger.debug( 'wfDict: %s' % (wfDict) ) if len(flowViews) == 1: viewTarget = flowViews[0].viewTarget else: for flowCode in paramFlowDict: params = paramFlowDict[flowCode] check = True numberEval = 0 for param in params: if wfDict['data'].has_key(param.name): if param.operator == Choices.OP_EQ: check = wfDict['data'][param.name] == param.value elif param.operator == Choices.OP_LT: check = wfDict['data'][param.name] < param.value elif param.operator == Choices.OP_GT: check = wfDict['data'][param.name] > param.value elif param.operator == Choices.OP_NE: check = wfDict['data'][param.name] != param.value if check == True: numberEval += 1 if check == True and numberEval > 0: viewTarget = flowViews.filter(flowView__code=flowCode).viewTarget break return viewTarget
[docs] def put_params(self, **argsDict): """Put list of workflow parameters in context @param argsDict: Argument dictionary""" flowCode = self._ctx.flowCode flow = self._dbWorkflow.get(code=flowCode) #@UnusedVariable if not self.__wfData: self.__wfData = get_blank_wf_data({}) nameList = argsDict.keys() params = self._dbParam.search(name__in=nameList) if len(params) != 0: for name in argsDict: checkType = True paramFilter = params.filter(name=name) if not paramFilter: raise XpMsgException(None, _('Parameter "') + str(name) + _('" has not been registered')) paramDbType = paramFilter[0].paramType paramType = type(argsDict[name]) if paramDbType == Choices.BASIC_TYPE_BOOL: checkType = paramType == types.BooleanType elif paramDbType == Choices.BASIC_TYPE_DATE: checkType = paramType is datetime.date elif paramDbType == Choices.BASIC_TYPE_FLOAT: checkType = paramType == types.FloatType elif paramDbType == Choices.BASIC_TYPE_INT: checkType = paramType == types.IntType elif paramDbType == Choices.BASIC_TYPE_LONG: checkType = paramType == types.LongType elif paramDbType == Choices.BASIC_TYPE_STR: checkType = paramType == types.StringType elif paramDbType == Choices.BASIC_TYPE_TIME: checkType = paramType is datetime.time #paramValue, created = self._dbWFParams.getCreate() if checkType == True: self.__wfData['data'][name] = argsDict[name] else: raise XpMsgException(None, _('Error in parameter type. "') + str(paramDbType) + _('" was expected and "') + str(paramType) + _('" was provided for parameter "') + str(name) + '"') else: raise XpMsgException(None, _('Parameters "') + ''.join(nameList) + _('" have not been registered'))
[docs] def save(self, wf_user_id, flow_code): """Saves the workflow into database for user @param user: User @param flowCode: Flow code""" logger.debug( '__wfData: %s' % (self.__wfData) ) flows = self._dbWFData.search(userId=wf_user_id, flow__code=flow_code) flow = flows[0] if flows > 0: flowData = _jsf.decode64dict(flow.data) for name in self.__wfData['data']: flowData['data'][name] = self.__wfData['data'][name] else: raise XpMsgException(None, _('Flow data not found')) #if self.__wfData['viewName'] != '': flowData['viewName'] = self.__wfData['viewName'] view = self._dbView.get(name=self.__wfData['viewName']) flow.view = view logger.debug( 'save :: flowData: %s' % (flowData) ) flow.data = _jsf.encode64Dict(flowData) flow.save() return flow
[docs] def reset_flow(self, wf_user_id, flow_code, view_name): """Reset flow. It deletes all workflow variables and view name @param wf_user_id: Workflow User Id @param flow_code: Flow code""" try: flowData = self.resolveFlowDataForUser(wf_user_id, flow_code) logger.debug( 'resetFlow :: flowData: %s' % (flowData) ) self.__wfData = get_blank_wf_data({}) self.__wfData['viewName'] = view_name logger.debug( '__wfData: %s' % (self.__wfData) ) # Update flow data view = self._dbView.get(name=view_name) flowData.data = _jsf.encode64Dict(self.__wfData) flowData.view = view flowData.save() except XpMsgException: # Create flow data logger.debug( 'create flow... %s' % (wf_user_id) ) self.__wfData = get_blank_wf_data({}) self.__wfData['viewName'] = view_name logger.debug( '__wfData: %s' % (self.__wfData) ) view = self._dbView.get(name=view_name) workflow = self._dbWorkflow.get(code=flow_code) self._dbWFData.create(userId=wf_user_id, flow=workflow, data = _jsf.encode64Dict(self.__wfData), view=view)
[docs] def set_view_name(self, view_name): """Set view name in Workflow @param view_name: View name""" logger.debug( 'setViewName :: %s' % (self.__wfData) ) self.__wfData['viewName'] = view_name logger.debug( self.__wfData )
[docs] def get_view_name(self): """Get workflow view name. @return: viewName""" return self.__wfData['viewName']
[docs] def get_param(self, name): """Get workflow parameter from context @param name: Name @return: Param Value""" return self.__wfData['data'][name]
[docs] def get_param_from_ctx(self, name): """Get flow parameter from context. @param name: Parameter name @return: Parameter value""" flowDataDict = self._ctx.flowData logger.debug( 'flowDataDict: %s type:%s' % (flowDataDict, type(flowDataDict)) ) logger.debug( 'wfData: %s' % (self.__wfData) ) return flowDataDict['data'][name]
[docs] def build_flow_data_dict(self, flow_data): """Build the flow data dictionary having the flowData instance. @param flowData: Flow data @return: flow_data_dict""" flowDataDict = _jsf.decode64dict(flow_data.data) logger.debug( 'build :: flowDataDict: %s' % (flowDataDict) ) return flowDataDict
[docs] def get_flow_data_dict(self, wf_user_id, flow_code): """Get flow data dictionary for user and flow code @param wf_user_id: Workflow user id @param flow_code: flowCode @return: flow_data_dict : Dictionary""" flowData = self.resolveFlowDataForUser(wf_user_id, flow_code) flowDataDict = _jsf.decode64dict(flowData.data) logger.debug( 'get :: flowDataDict: %s' % (flowDataDict) ) return flowDataDict
[docs] def get_flow_view_by_action(self, action_name): """Get flow by action name. It queries the workflow data and returns flow associated with actionName @param action_name: Action name @return: flow_view: Workflow view""" flowView = self._dbWFView.get(action__name=action_name) return flowView
[docs] def get_view(self, wf_user_id, flow_code): """Get view from flow @param wf_user_id: User @param flow_code: Flow code @return: view_name""" flowDataDict = self.getFlowDataDict(wf_user_id, flow_code) viewName = flowDataDict['viewName'] return viewName
[docs] def get_view_params(self, flow_code, view_name): """Get view entry parameters for view and flow @param flow_code: Flow code @param view_name: View name @return: param_dict""" params = self._dbWFParams.search(flowView__flow__code=flow_code, flowView__viewTarget__name=view_name) logger.debug( 'params: %s' % (params) ) paramDict = {} for param in params: paramDict[param.paramView.name] = param.paramView.value return paramDict
[docs] def is_last_view(self, view_name_source, view_name_target, action_name): """Checks if view is last in flow.""" flowsView = self._dbWFView.search(viewSource__name=view_name_source, action__name=action_name).order_by('-order') flowView = flowsView[0] if len(flowsView) != 0 else None isLastView = False if flowView != None and flowView.viewTarget.name == view_name_target: isLastView = True return isLastView
[docs] def is_first_view(self, flow_code, view_name): """Checks if view is first in flow. It uses field 'order' to determine if is first view.""" check = False flowViewStart = self._dbWFView.get(flow__code=flow_code, order=10) if flowViewStart.viewSource.name == view_name: check = True else: check = False return check
[docs] def remove_data(self, wf_user_id, flow_code): """Removes the workflow data for user or session.""" flowData = self.resolveFlowDataForUser(wf_user_id, flow_code) self._dbWFData.deleteById(flowData.id, real=True)
class CommonBusiness ( object ): """ Common Business class for ximpia business logic. **Attributes** * ``ctx``:Dict : Context """ _ctx = None def __init__(self, ctx): self._ctx = ctx self._ctx_min = copy.deepcopy(self._ctx) self._ctx_min.to_min() def _instances(self, *args): """ Builds instances list from list of classes. Inyects context. ** Attributes ** * ``*args``: List of class names or path to class names. ** Returns ** List of business, data instances with context inyected """ instances = get_instances(args, self._ctx_min) return instances