# # Copyright (c) 2005-2006, John Mettraux, OpenWFE.org # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # . Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # # . Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # . Neither the name of the "OpenWFE" nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. # # $Id: codec.rb 2865 2006-06-23 14:54:07Z jmettraux $ # # # "hecho en Costa Rica" # #require 'base64' require 'rexml/document' require 'definitions' require 'utils' require 'workitem' module OpenWFE # # Takes as input some XML element and returns is decoded (as an instance) # def OpenWFE.decode (xmlElt) return nil if not xmlElt #puts "decode() xmlElt.name is >#{xmlElt.name}<" return decodeList(xmlElt) if xmlElt.name == STORES return decodeStore(xmlElt) if xmlElt.name == STORE return decodeList(xmlElt) if xmlElt.name == HEADERS return decodeHeader(xmlElt) if xmlElt.name == HEADER return decodeLaunchOk(xmlElt) if xmlElt.name == OK return decodeList(xmlElt) if xmlElt.name == HISTORY return decodeHistoryItem(xmlElt) if xmlElt.name == HISTORY_ITEM return decodeList(xmlElt) \ if xmlElt.name == FLOW_EXPRESSION_IDS return decodeFlowExpressionId(xmlElt) \ if xmlElt.name == FLOW_EXPRESSION_ID return decodeInFlowWorkItem(xmlElt) \ if xmlElt.name == IN_FLOW_WORKITEM return decodeList(xmlElt) if xmlElt.name == LAUNCHABLES return decodeLaunchable(xmlElt) if xmlElt.name == LAUNCHABLE return decodeList(xmlElt) if xmlElt.name == EXPRESSIONS return decodeExpression(xmlElt) if xmlElt.name == EXPRESSION return decodeAttribute(xmlElt.elements[1]) if xmlElt.name == ATTRIBUTES # # default return decodeAttribute(xmlElt) #raise \ # ArgumentException, \ # "Cannot decode : '"+xmlElt.name+"' "+xmlElt.to_s() end # # Takes some OpenWFE Ruby instance and returns it as XML # def OpenWFE.encode (owfeData) #puts "encode() #{owfeData.inspect}" return encodeLaunchItem(owfeData) \ if owfeData.kind_of?(LaunchItem) return encodeFlowExpressionId(owfeData) \ if owfeData.kind_of?(FlowExpressionId) return encodeInFlowWorkItem(owfeData) \ if owfeData.kind_of?(InFlowWorkItem) raise \ ArgumentException, \ "Cannot encode : "+owfeData.inspect() end private # # DECODE # def OpenWFE.decodeList (xmlElt) l = [] xmlElt.elements.each do |elt| #puts " ... #{elt.inspect()}" l.push(decode(elt)) end return l end def OpenWFE.decodeLaunchable (xmlElt) launchable = Launchable.new() launchable.url = xmlElt.attributes[URL] launchable.engineId = xmlElt.attributes[ENGINE_ID] return launchable end def OpenWFE.decodeExpression (xmlElt) exp = Expression.new() #exp.id = decode(firstElement(xmlElt, "//"+FLOW_EXPRESSION_ID)) exp.id = decode(firstElement(xmlElt)) exp.applyTime = xmlElt.attributes[APPLY_TIME] exp.state = xmlElt.attributes[STATE] exp.stateSince = xmlElt.attributes[STATE_SINCE] return exp end def OpenWFE.decodeStore (xmlElt) store = Store.new() store.name = xmlElt.attributes[NAME] store.workitemCount = xmlElt.attributes[WORKITEM_COUNT] store.workitemCount = Integer(store.workitemCount) store.permissions = xmlElt.attributes[PERMISSIONS] return store end def OpenWFE.decodeHeader (xmlElt) header = Header.new() header.lastModified = xmlElt.attributes[A_LAST_MODIFIED] header.locked = parseBoolean(xmlElt.attributes[A_LOCKED]) header.flowExpressionId = decode(firstElement(xmlElt, FLOW_EXPRESSION_ID)) header.attributes = decode(firstElement(xmlElt, ATTRIBUTES)) return header end def OpenWFE.decodeFlowExpressionId (xmlElt) fei = FlowExpressionId.new() fei.owfeVersion = xmlElt.attributes[OWFE_VERSION] fei.engineId = xmlElt.attributes[ENGINE_ID] fei.initialEngineId = xmlElt.attributes[INITIAL_ENGINE_ID] fei.workflowDefinitionUrl = xmlElt.attributes[WORKFLOW_DEFINITION_URL] fei.workflowDefinitionName = xmlElt.attributes[WORKFLOW_DEFINITION_NAME] fei.workflowDefinitionRevision = xmlElt.attributes[WORKFLOW_DEFINITION_REVISION] fei.workflowInstanceId = xmlElt.attributes[WORKFLOW_INSTANCE_ID] fei.expressionName = xmlElt.attributes[EXPRESSION_NAME] fei.expressionId = xmlElt.attributes[EXPRESSION_ID] #puts " ... fei.expressionName is >#{fei.expressionName}<" #puts " ... fei.wfid is >#{fei.workflowInstanceId}<" return fei end def OpenWFE.decodeAttribute (xmlElt) #puts "decodeAttribute() '#{xmlElt.name}' --> '#{xmlElt.text}'" # # atomic types return xmlElt.text if xmlElt.name == E_STRING return Integer(xmlElt.text) if xmlElt.name == E_INTEGER return Integer(xmlElt.text) if xmlElt.name == E_LONG return Float(xmlElt.text) if xmlElt.name == E_DOUBLE return parseBoolean(xmlElt.text) if xmlElt.name == E_BOOLEAN return xmlElt if xmlElt.name == E_XML return Base64Attribute.new(xmlElt.txt) if xmlElt.name == E_BASE64 # # composite types return decodeList(xmlElt) if xmlElt.name == E_LIST if xmlElt.name == E_SMAP or xmlElt.name == E_MAP map = {} map[MAP_TYPE] = xmlElt.name #xmlElt.elements.each("//"+M_ENTRY) do |e| xmlElt.elements.each(M_ENTRY) do |e| #puts "decodeAttribute() >#{e}<" decodeEntry(e, map) end return map end #puts docToString(xmlElt.document()) raise \ ArgumentError, \ "Cannot decode <#{xmlElt.name}/> in \n"+\ docToString(xmlElt.document()) end def OpenWFE.decodeEntry (xmlElt, map) key = xmlElt.elements[1] val = xmlElt.elements[2] # # this parse method supports the old style and the [new] light # style/schema # key = key.elements[1] if key.name == M_KEY val = val.elements[1] if val.name == M_VALUE key = decode(key) val = decode(val) #puts "decodeEntry() k >#{key}< v >#{val}<" #puts "decodeEntry() subject '#{val}'" if key == '__subject__' map[key] = val end def OpenWFE.parseBoolean (string) return string.strip.downcase == 'true' end def OpenWFE.decodeHistoryItem (xmlElt) hi = HistoryItem.new hi.author = xmlElt.attributes[A_AUTHOR] hi.date = xmlElt.attributes[A_DATE] hi.host = xmlElt.attributes[A_HOST] hi.text = xmlElt.text hi.wfdName = xmlElt.attributes[WORKFLOW_DEFINITION_NAME] hi.wfdRevision = xmlElt.attributes[WORKFLOW_DEFINITION_REVISION] hi.wfInstanceId = xmlElt.attributes[WORKFLOW_INSTANCE_ID] hi.expressionId = xmlElt.attributes[EXPRESSION_ID] return hi end def OpenWFE.decodeLaunchOk (xmlElt) sFei = xmlElt.attributes[A_FLOW_ID] return true if not sFei return FlowExpressionId.strToFei(sFei) end def OpenWFE.decodeInFlowWorkItem (xmlElt) wi = InFlowWorkItem.new() wi.lastModified = xmlElt.attributes[A_LAST_MODIFIED] wi.attributes = decode(firstElement(xmlElt, ATTRIBUTES)) wi.participantName = xmlElt.attributes[A_PARTICIPANT_NAME] wi.flowExpressionId = decode(firstElement(firstElement(xmlElt, E_LAST_EXPRESSION_ID), FLOW_EXPRESSION_ID)) wi.dispatchTime = xmlElt.attributes[A_DISPATCH_TIME] # TODO : decode filter wi.history = decode(firstElement(xmlElt, HISTORY)) return wi end # # ENCODE # def OpenWFE.docToString (xml, decl=true) s = "" if decl and xml[0].kind_of? REXML::XMLDecl xml << REXML::XMLDecl.new() end xml.write(s, 0) return s end def OpenWFE.encodeItem (item, elt) elt.attributes[A_LAST_MODIFIED] = item.lastModified eAttributes = REXML::Element.new(ATTRIBUTES) eAttributes << encodeAttribute(item.attributes) elt << eAttributes end def OpenWFE.encodeLaunchItem (launchitem) doc = REXML::Document.new() root = REXML::Element.new(E_LAUNCHITEM) encodeItem(launchitem, root) root.attributes[WORKFLOW_DEFINITION_URL] = \ launchitem.workflowDefinitionUrl # TODO : # # - encode descriptionMap # # - replyTo is not necessary #doc.root = root doc << root return docToString(doc) end def OpenWFE.encodeInFlowItem (item, elt) encodeItem(item, elt) elt.attributes[A_PARTICIPANT_NAME] = item.participantName eLastExpressionId = REXML::Element.new(E_LAST_EXPRESSION_ID) eLastExpressionId << encodeFlowExpressionId(item.lastExpressionId) elt << eLastExpressionId end def OpenWFE.encodeInFlowWorkItem (item) doc = REXML::Document.new() root = REXML::Element.new(IN_FLOW_WORKITEM) encodeInFlowItem(item, root) root.attributes[A_DISPATCH_TIME] = item.dispatchTime # add filter ? no encodeHistory(item, root) doc << root s = docToString(doc) #puts "encoded :\n#{s}" return s end def OpenWFE.encodeHistory (item, elt) eHistory = REXML::Element.new(HISTORY) item.history.each do |hi| ehi = REXML::Element.new(HISTORY_ITEM) ehi.attributes[A_AUTHOR] = hi.author ehi.attributes[A_DATE] = hi.date ehi.attributes[A_HOST] = hi.host ehi.attributes[WORKFLOW_DEFINITION_NAME] = hi.wfdName ehi.attributes[WORKFLOW_DEFINITION_REVISION] = hi.wfdRevision ehi.attributes[WORKFLOW_INSTANCE_ID] = hi.wfInstanceId ehi.attributes[EXPRESSION_ID] = hi.expressionId eHistory << ehi end elt << eHistory end def OpenWFE.encodeAttribute (att) #puts "encodeAttribute() att.class is #{att.class}" return encodeAtomicAttribute(E_STRING, att) \ if att.kind_of? String return encodeAtomicAttribute(E_INTEGER, att) \ if att.kind_of? Fixnum return encodeAtomicAttribute(E_DOUBLE, att) \ if att.kind_of? Float return encodeXmlAttribute(att) \ if att.kind_of? REXML::Element return encodeAtomicAttribute(E_BOOLEAN, true) \ if att.kind_of? TrueClass return encodeAtomicAttribute(E_BOOLEAN, false) \ if att.kind_of? FalseClass return encodeBase64Attribute(att) \ if att.kind_of? Base64Attribute # # missing : BASE64... return encodeMapAttribute(att) if att.kind_of? Hash return encodeListAttribute(att) if att.kind_of? Array # # default return encodeAtomicAttribute(E_STRING, att) #raise \ # ArgumentException, \ # "Cannot encode attribute of class '#{att.class}'" end def OpenWFE.encodeXmlAttribute (elt) return elt if elt.name == E_XML # # else, wrap within ... e = REXML::Element.new(E_XML) e << elt return e end def OpenWFE.encodeBase64Attribute (att) e = REXML::Element.new(E_BASE64) e.text = att.content return e end def OpenWFE.encodeAtomicAttribute (name, value) elt = REXML::Element.new(name) #elt << REXML::Text.new(value.to_s()) elt.add_text(value.to_s()) return elt end def OpenWFE.encodeListAttribute (list) elt = REXML::Element.new(E_LIST) list.each do |e| elt << encodeAttribute(e) end return elt end def OpenWFE.encodeMapAttribute (hash) name = hash[MAP_TYPE] name = 'map' if name == nil elt = REXML::Element.new(name) hash.each_key do |key| next if key == MAP_TYPE eEntry = REXML::Element.new(M_ENTRY) val = hash[key] eEntry << encodeAttribute(key) eEntry << encodeAttribute(val) elt << eEntry end return elt end def OpenWFE.encodeFlowExpressionId (fei) elt = REXML::Element.new(FLOW_EXPRESSION_ID) elt.attributes[OWFE_VERSION] = fei.owfeVersion elt.attributes[ENGINE_ID] = fei.engineId elt.attributes[INITIAL_ENGINE_ID] = fei.initialEngineId elt.attributes[WORKFLOW_DEFINITION_URL] = fei.workflowDefinitionUrl elt.attributes[WORKFLOW_DEFINITION_NAME] = fei.workflowDefinitionName elt.attributes[WORKFLOW_DEFINITION_REVISION] = fei.workflowDefinitionRevision elt.attributes[WORKFLOW_INSTANCE_ID] = fei.workflowInstanceId elt.attributes[EXPRESSION_NAME] = fei.expressionName elt.attributes[EXPRESSION_ID] = fei.expressionId return elt end end