#!/usr/local/bin/python

#   FILE: PylogCGI.py -- A cgi interface to the Pylog class, which allows
#         restoring SWI Prolog states over multiple CGI processes.
# AUTHOR: W. Michael Petullo, wp0002@drake.edu
#   DATE: 3 OCT 1997
#
# Copyright (c) 1999 W. Michael Petullo
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice in the documentation and/or other materials provided with
#    the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
import genCGI, Pylog, os, sys, time

# ============================ PylogCGI =======================================
class PylogCGI (genCGI.ParseMixin, genCGI.Verbose_Mixin, genCGI.cgiBase):
	
# ============================ LoadState () ===================================
	def LoadState (self, state):
	#  PRE: state is assigned previous state
	# POST: prolog is an instance of a Pylog
	#   &&  if a previous state exists, Pylog has loaded it
		if (state == "none"):
			self.prolog = Pylog.Pylog ()
		else:
			filename = ".incoming%s" % os.getpid ()
			# ASSERT: a temporary file with a unique name exists for
			#         saving the previous state to
			file = open (filename, 'w')
			for line in state:
				file.write (line)
				# ASSERT: temporary file contains previous state
			self.prolog = Pylog.Pylog ("/usr/local/bin/pl", ("pl", "-x", filename))
			os.unlink (filename)
			# ASSERT: temporary file is deleted
	
# ============================ SaveState () ===================================
	def SaveState (self):
	# POST: FCTVAL == saved prolog state
		filename = ".outgoing%s" % os.getpid ()
		self.prolog.Query ("qsave_program(\"%s\")."% filename)
		# REPLACE!
		time.sleep (3)
		# ASSERT: a temporary file with a unique name contains the
		#         current state
		file = open (filename, 'r')
		state = ""
		lines = file.readlines ()
		os.unlink (filename)
		# ASSERT: temporary file is deleted
		for l in lines:
			state = state + l
			# ASSERT: state contains current state
		return (state)
		
	def GenerateFillers (self, form):
	# NOTE: This is to be overloaded in sub-class.
		return ({})
		
# ============================ prepare_response () ============================
	def prepare_response (self, form):
	#  PRE: form.keys () == ['INPUT', 'STATE']
	# POST: self.fillers contains proper values to create a responce
	# NOTE: The dictionary's keys contain the following:
	#                'RESPONSE' -- the responce from the shrink
	#                'STATE'    -- the saved Prolog state for the next
	#                              query.
	#       Overloads GGIbase class.
		self.LoadState (form['STATE'])
		fill = self.GenerateFillers (form)
		fill['STATE'] = self.SaveState ()
		self.prolog.Shutdown ()
		self.fillers = fill
		
if (__name__ == "__main__"):
	PylogCGI ().GO ()
