<@script name="XglCompiler" hide="y"> Implements the XGL Compiler (c) SAP AG 2003-2006. All rights reserved. #CACHE[OFF] function XglCompiler() { this.scenarioCompiler = new XglScenarioCompiler(); this.processCompiler = new XglProcessCompiler(); } XglCompiler.prototype.compileUnit = function(unit, out, debugMode) { if (ISA(unit,'gml2:Process','gml2:BlackProcess')) { var compiler = this.processCompiler; } else { var compiler = this.scenarioCompiler; } compiler.unit = unit; compiler.out = out; compiler.debugMode = debugMode; compiler.damageScope = debugMode ? #[XGL_DAMAGE_FULL] : unit.xglDirty; if (compiler.damageScope==#[XGL_DAMAGE_NONE]) return; try { compiler.compileHeader(); compiler.compileBody(); compiler.compileFooter(); compiler.translate(); if (!debugMode && out.errorsCount==0) unit.clearXglDirty(); } catch(e) { out.error('#TEXT[XMSG_CP_ERR_INTERNAL]' + e.description); } } XglCompiler.prototype.compileHeader = function() { var out=this.out, unit=this.unit; this.root = unit.root; this.units = {}; this.unitsCounter = 0; this.xglver = '2.2'; this.xg_ns = 'http:/'+'/www.sap.com/visualcomposer/2006/xgl' + this.xglver; this.rnt_ns = 'http:/'+'/www.sap.com/visualcomposer/2006/runtime'; this.dbg_ns = 'http:/'+'/www.sap.com/visualcomposer/2008/debugger'; this.xns = {xg:this.xg_ns}; this.rns = {rnt:this.rnt_ns}; this.dns = {dbg:this.dbg_ns}; this.nsBookmark = null; this.de = $ENV.dynexp; this.de.resetTranslations(); RULE('setDynExpContext',unit); this.index = { nodes:{}, infosets:{}, infoshapes:{}, infoset_holders:{}, interactors:{}, processors:{}, infoactors:{}, operators:{}, relays:{}, enums:{}, actions:{}, specific_events:{}, generic_events:{}, post_plans:[], palettes:{}, systems:{}, roles:{}, references:{}, popups:{}, propsMetadata:{} } this.getUnitAlias(unit); var urn = unit.urn || unit.id; var folder = out.createFolder(null, urn); var xglfile = out.createFile(folder, urn, 'xgl'); folder.caption = (unit.name||urn); xglfile.caption = (unit.name||urn) + '.xgl'; folder.hint = 'Folder: '+urn; xglfile.hint = 'File: '+urn+'.xgl'; var tagName = 'xg:' + unit.Class.metadata.xgl.type; var props = this.getProps(unit,'',{urn:1,description:1}); props.simple['timestamp'] = (new Date()).getTime(); this.printSimpleProps(tagName,props.simple,props.complex); this.nsBookmark = out.getBookmark(); this.printComplexProps(props.complex); out.beginTag('rnt:Implementations'); var rntData={runtimeMode:'new'}, empty=true; if (ISA(unit,'gml2:BlackBox')) { for (var k in unit.runtimeData) rntData[k] = unit.runtimeData[k]; } else { rntData.runtimeVersion = this.xglver; rntData.runtimeEngine = 'XGL'; } for (var param in rntData) { empty = false; var prefix = param.substring(0,param.indexOf(':')); if(!prefix || (prefix in this.rns)) continue; var ns = this.rnt_ns + '/' + prefix; this.rns[prefix] = ns; } if (!empty) out.addTag('rnt:Implementation',rntData); out.endTag(); if (ISA(unit, 'gml2:Scenario')) { out.beginTag('xg:ExceptionHandlers'); if (unit.msgErrorLevel != 'none') out.addTag('xg:DisplayException',{severity:unit.msgErrorLevel,output:'message'}); if (unit.statusErrorLevel != 'none') out.addTag('xg:DisplayException',{severity:unit.statusErrorLevel,output:'status'}); if (unit.logErrorLevel != 'none') out.addTag('xg:DisplayException',{severity:unit.logErrorLevel,output:'logfile'}); if (unit.promptErrorLevel != 'none') out.addTag('xg:DisplayException',{severity:unit.promptErrorLevel,output:'prompt'}); out.endTag(); } } XglCompiler.prototype.compileBody = function() { // override this method on subclasses } XglCompiler.prototype.compileFooter = function() { var out=this.out; this.printNSList(); out.endTag(); } XglCompiler.prototype.translate = function() { var out=this.out, de=this.de, urn = this.unit.urn || this.unit.id, locale = $ENV.model.getDCInfoProperty(this.unit.impl_location,$ENV.model.MASTER_LANGUAGE) || 'en'; var xlffile = out.createFile(urn, urn, 'xlf'); xlffile.caption = (this.unit.name||urn)+ '.xlf'; xlffile.hint = 'File: '+urn+'.xlf'; out.beginTag('xliff',{version:'1.1'}); out.beginTag('file',{'source-language':locale,datatype:'javaPropertyResourceBundle'}); out.beginTag('header'); out.addTag('skl'); out.addTag('phase-group'); out.beginTag('s2x',{xmlns:'http:/'+'/www.sap.com'}); out.beginTag('dtr'); out.addTag('sc'); out.endTag(); //dtr out.beginTag('giltDirectives'); out.addTag('develContact',null,'sapuser@sap.com'); out.addTag('domain',null,'Cross Applications'); out.addTag('originalLocale',{'xml:lang':locale}); out.addTag('maxLength',null,'255'); out.endTag(); //giltDirectives out.endTag(); //s2x out.endTag(); //header out.beginTag('body'); translateBody(); out.endTag(); //body out.endTag(); //file out.endTag(); //xliff function translateBody() { var R = {}; for (var k in de.translations['user']) { var node = de.translations['user'][k]; classifyNode(node); } for (var k in de.translations['default']) { var node = de.translations['default'][k]; classifyNode(node); } for (var k in R) { out.beginTag('group',{restype:k}); var nodes = R[k], node; for (var i=0,len=nodes.length; i0) { props.precedents = step.precedents.join(' '); } switch (step.type) { case 'Invalidate': props.targets = step.targets; if (this.debugMode) addDebugInfo(step,node,props); out.addTag('xg:Invalidate',props); break; case 'Map': addFlowCondition(step,node,props); var mapping = step.map; props.source = mapping.sourceInfoset; props.target = mapping.targetInfoset; if (this.debugMode) addDebugInfo(step,node,props); out.beginTag('xg:Map',props); this.printAssigns(mapping,holder,desc); out.endTag(); break; case 'Copy': addFlowCondition(step,node,props); props.source = holders[node.source.id]; props.target = holders[node.target.id]; if (this.debugMode) addDebugInfo(step,node,props); out.addTag('xg:Copy',props); break; case 'Trans': addFlowCondition(step,node,props); var sparent=node.source.parent, tparent=node.target.parent; props.source = this.getElementId(sparent); props.target = this.getElementId(tparent); if (this.debugMode) addDebugInfo(step,node,props); out.addTag('xg:Trans',props); break; case 'Eval': props.source = this.getElementId(node); if (this.debugMode) addDebugInfo(step,node,props); out.addTag('xg:Eval',props); break; } } out.endTag(); } out.endTag(); function addFlowCondition(step,node,props) { if (step.type == 'Map') { if (node.assignMode && node.assignMode != 'all') props.assignMode = node.assignMode; if (node.selectMode && node.selectMode != 'current') props.selectMode = node.selectMode; } else if (step.type == 'Copy') { if (node.selectMode && node.selectMode != 'all') props.selectMode = node.selectMode; } if (node.guard && node.guard+'' != 'true') { RULE('setDynExpContext', compiler.unit, node); var guard = compiler.parseExpr(node.guard,'Boolean',node,'guard',node,'Guard condition'); if (guard !== null) props.guard = guard; } } function addDebugInfo(step,node,props) { var participants = {}, infosets = compiler.index.infosets; if (!ISEMPTY(node)) participants[node.id] = true; if (step.type == 'Invalidate') { var targets = KEYS2OBJ(step.targets); for (var set in targets) { var partners = infosets[set].partners; for (var k in partners) participants[k] = true; } } else if (step.type == 'Eval') { if (node.id in holders) { var set = holders[node.id]; var partners = infosets[set].partners; for (var k in partners) participants[k] = true; } } props['dbg:participants'] = OBJ2KEYS(participants); } } //=============================================================== //+++++++++++++++++++++ RESOURCES Methods +++++++++++++++++++++++ //=============================================================== XglCompiler.prototype.compileImages = function() { } XglCompiler.prototype.compilePalettes = function() { var out=this.out, palettes=this.index.palettes; out.beginTag('xg:Palettes'); for (var k in palettes) { var palette = $ENV.palettes.getPalette(k); out.beginTag('xg:Palette',{name:k}); for (var i=0,len=palette.length; i',' ' + N.join(' ') + '>'); } XglCompiler.prototype.parseExpr = function(expr,type,elem,prop,view_elem,view_prop,scope,ignore_cache) { var de = this.de, out = this.out, type = type || 'String'; if (this.damageScope <= #[XGL_DAMAGE_DATA] && !ignore_cache) { var cache = NVL(elem.xglDECache[prop]); if (cache !== null) { this.loadTranslationState(cache); return cache.val; } } expr = NVL(expr,'') + ''; de.setExpectedType(type); de.setTranslationScope(scope||''); de.parse(de.clearExprComments(expr)); if (de.error) { out.error('#TEXT[XMSG_CP_ERR_METADATA_COMPILE]'.replace('{0}', view_prop) + ' - ' + de.error, view_elem); if (!ignore_cache) delete elem.xglDECache[prop]; return null; } var val = de.xglPrint(); if (!ignore_cache) { var cache = {val:val, custom:{}}; this.cacheTranslationState(cache); elem.xglDECache[prop] = cache; } return val; } XglCompiler.prototype.translateExpr = function(expr,exprType,transType,elem,prop,view_elem,view_prop,scope,ignore_cache) { var out = this.out, de = this.de, tval = expr, ttype; if (!expr) return ''; var isExpr = !ISNULL(exprType); if (isExpr) { var val = this.parseExpr(expr,exprType,elem,prop,view_elem,view_prop,scope,ignore_cache); if (val === null) return null; if (!de.isLiteral) return val; tval = (de.tree && de.tree.value) || expr; } ttype = transType; if (!transType) return (isExpr? val : expr); if (typeof transType == 'function') { try { ttype = transType(elem,prop); } catch (e) { out.error('#TEXT[XMSG_CP_ERR_METADATA_TRANSLATE]'+' "'+view_prop+'"',view_elem); if (!ignore_cache) elem.invalidateXglDECache(prop); return null; } } var trans_expr = '=TRANSLATE("'+tval.replace(/\\/g,'\\\\').replace(/\"/g,'\\"')+'","'+ttype+'")'; if (!ignore_cache) elem.invalidateXglDECache(prop); return this.parseExpr(trans_expr,'String',elem,prop,view_elem,view_prop,scope,ignore_cache); } XglCompiler.prototype.cacheTranslationState = function(cacheRecord) { if (cacheRecord === null) return; var de = this.de, custom = cacheRecord.custom, keys = {}, found = false; for (var key in de.translationKeys) { found = true; var rec = de.translationKeys[key]; keys[key] = {key:rec.key, text:rec.text, tType:rec.tType, scope:rec.scope}; } if (found) { if (!ISEMPTY(custom['keys'])) { var curr_keys = custom['keys']; for (var k in curr_keys) keys[k] = curr_keys[k]; } custom['keys'] = keys; } custom['isLiteral'] = de.isLiteral; } XglCompiler.prototype.loadTranslationState = function(cacheRecord) { if (cacheRecord === null) return; var de = this.de, custom = cacheRecord.custom, keys = custom.keys; if (!ISEMPTY(keys)) { for (var key in keys) { var rec = keys[key]; de.addTranslationKey(rec.key, rec.text, rec.tType, rec.scope); } } if ('isLiteral' in custom) de.isLiteral = custom['isLiteral']; } XglCompiler.prototype.extractReference = function(elem, silent) { var index=this.index; var targetComponent = elem.targetComponent || ''; if (!targetComponent) { if(!silent && !this.debugMode) this.out.error('#TEXT[XMSG_MISSING_REF]'.replace('{0}', '' + elem.name + ''),elem); return ''; } var component = targetComponent.getComponent(); if(targetComponent.interfaceChecksum != (component && component.interfaceChecksum) ){ var cp = $ENV.createObject('core.gml2:ConflictProvider'); cp.compareComponents(component, component, elem); if( cp.hasErrors() || cp.hasWarnings() ) this.out.warning( '#TEXT[YMSG_OUT_OFF_SYNC_INTERFACE]'.replace('{0}',elem.name), elem); } index.references[targetComponent.id] = {object:targetComponent}; return targetComponent.id; } XglCompiler.prototype.extractInfosets = function(node) { var index=this.index, out=this.out, compiler=this; var holders=index.infoset_holders, infoshapes=index.infoshapes, infosets=index.infosets; var elem = node.object, synthetic=BOOL(node.synthetic); if (ISA(elem,'gml2:DataBoundInteractor')) { if (!elem.isValidViewNode()) { out.error('#TEXT[XMSG_CP_ERR_INVALID_VIEWNODE]'+' "'+elem.viewNode+'"',elem); return; } var set = createInfoview(elem); var base = createBaseInfoset(elem); node.set = set; holders[elem.id] = base; infosets[set].base = base; for (var k in elem.plugs) { var plug = elem.plugs[k]; var pset = (ISA(plug,'gml2:PlugIn')? base : set); holders[plug.id] = pset; } } else if (ISA(elem,'gml2:CompositeInteractor','gml2:Infoactor','gml2:GotoView','gml2:BasicStep')) { for (var k in elem.plugs) { var plug = elem.plugs[k], pset; if (!ISA(plug,'dev:IInfoset')) continue; if (ISA(plug,'gml2:DTPlugIO')) { var res = plug.checkBoundInfosets(); if (!this.validateResults(res,elem)) continue; if (plug.infosetOwner == 'outer' && elem.getBindInLink(plug)) pset = plug.getInfosetId(); else pset = createOwnInfoset(plug,true); } else pset = createOwnInfoset(plug,true); holders[plug.id] = pset; } } else if (ISA(elem,'gml2:Operator')) { var isShapeHolder = this.isShapeHolder(elem); var set = createOwnInfoset(elem,isShapeHolder); node.set = set; holders[elem.id] = set; var inPlugs = elem.getSourceInfosets(); for (var k in elem.plugs) { var plug = elem.plugs[k]; if (ISA(plug,'gml2:PlugOut')) holders[plug.id] = set; else { if (!(plug.id in inPlugs)) continue; if (synthetic) holders[plug.id] = set; else { // verify whether this plug should hold an infoset of its own var iholder = inPlugs[plug.id], ownSet = false; for (var l in plug.links) { var link = plug.links[l]; if (!this.skipCopyStep(link)) { ownSet = true; break; } } var iset = (ownSet? createFictiveInfoset(plug,iholder) : iholder.getInfosetId()); holders[plug.id] = iset; } } } } else if (ISA(elem,'gml2:Port')) { var set = createOwnInfoset(elem,true); node.set = set; holders[elem.id] = set; for (var k in elem.plugs) { var plug = elem.plugs[k]; holders[plug.id] = set; } } else if (ISA(elem,'gml2:DynamicEnum')) { var set = createOwnInfoset(elem,true); node.set = set; holders[elem.id] = set; for (var k in elem.plugs) { var plug = elem.plugs[k]; if (!ISA(plug,'dev:IInfoset')) continue; var pset = createOwnInfoset(plug,true); holders[plug.id] = pset; } } function createOwnInfoset(elem, isShapeHolder) { var infosetId = elem.getInfosetId(); if (infosetId in infosets) return infosetId; var data = null; if (ISA(elem,'gml2:PInitBlock')) { var res = elem.buildInitBlock(); if (compiler.validateResults(res,elem)) data = res.results; } var set = {id:infosetId,type:'S',data:data,holder:elem,partners:{}}; set.partners[elem.id] = true; attachInfoshape(elem,set,isShapeHolder); infosets[infosetId] = set; return infosetId; } function createBaseInfoset(elem) { var infosetId = elem.getBaseInfosetId(); if (infosetId in infosets) return infosetId; var baseElemId = infosetId.replace('_BASE',''); if (baseElemId != elem.id) return infosetId; var set = {id:infosetId,type:'B',data:null,holder:elem,partners:{}}; set.partners[elem.id] = true; attachInfoshape(elem,set); infosets[infosetId] = set; return infosetId; } function createInfoview(elem) { var infosetId = elem.getInfosetId(); if (infosetId in infosets) return infosetId; var set = {id:infosetId,type:'V',data:null,holder:elem,partners:{}}; set.partners[elem.id] = true; var source = elem.getSourceViewId(); set.source = source; set.viewNode = elem.getViewName(); var vfields = {}; for (var k in elem.fields) { var field = elem.fields[k]; if (field.kind == 'V') vfields[k] = field; } set.vfields = vfields; if (elem.hasOwnProperty('cursorReset')) set.cursorReset = elem.cursorReset; if (elem.hasFilterStep()) createFilterStep(); attachInfoshape(elem,set,true); infosets[infosetId] = set; return infosetId; function createFilterStep() { var res = elem.buildFilterClauses(), clauses = res.results; if (!compiler.validateResults(res,elem)) return; set.filter = clauses; } } function createFictiveInfoset(elem,holder) { // used for OPPlugIn var infosetId = elem.id; if (infosetId in infosets) return infosetId; var set = {id:infosetId,type:'S',data:null,holder:elem,partners:{}}; set.partners[elem.id] = true; var isShapeHolder = compiler.isShapeHolder(elem); var infoshape = holder.getInfoshape(); var shapeId = compiler.getElementId(infoshape); if (isShapeHolder) infoshapes[shapeId] = {object:infoshape,holder:holder}; set.shapeId = shapeId; infosets[infosetId] = set; return infosetId; } function attachInfoshape(elem,infoset,isShapeHolder) { var type = infoset.type, infosetId = infoset.id, shapeId = ''; var infoshape = ((type == 'B') ? elem.getBaseInfoshape() : elem.isa('#NS[DataBoundInteractor]') ? elem.getFlatInfoshape() : elem.getInfoshape()); if (infoshape) { shapeId = compiler.getElementId(infoshape); if (isShapeHolder) infoshapes[shapeId] = {object:infoshape,holder:elem}; } else { shapeId = compiler.getUnitAlias(elem.unit) + '_' + infosetId; var shape = ''; if (elem.cardinality) shape = elem.cardinality; else shape = (ISA(elem,'gml2:FormView')? '1..1' : '0..n'); infoshapes[shapeId] = {object:shape,holder:elem}; } infoset.shapeId = shapeId; } } XglCompiler.prototype.getInfosets = function(elems,excluders) { var I = {}, E = {}, holders=this.index.infoset_holders; if (!ISEMPTY(excluders)) E = this.getInfosets(excluders); for (var k in elems) { elem = elems[k]; if (ISA(elem,'gml2:DataStore')) continue; if (elem.id in holders) { var set = holders[elem.id]; if (!(set in E)) I[set] = true; } else { for (var p in elem.plugs) { var plug = elem.plugs[p]; if (ISA(plug,'gml2:CGPlugIn','gml2:DTPlugIO')) continue; if (plug.id in holders) { var set = holders[plug.id]; if (!(set in E)) I[set] = true; } } } } return I; } XglCompiler.prototype.printAssigns = function(mapping,holder,desc) { var out=this.out, index=this.index, de=this.de, compiler=this; var assigns=mapping.assigns, contextSet=mapping.sourceInfoset, contextElem=null; if (contextSet in index.infosets) contextElem = index.infosets[contextSet].holder; var prop = desc || 'map'; RULE('setDynExpContext', this.unit, contextElem, prop); for (var k in assigns) { var assign = assigns[k]; if (ISA(assign,'gml2:NodeAssign')) printNodeAssign(assign); else printFieldAssign(assign); } de.clearRelativeNode(); function printNodeAssign(assign) { var assignType = LOWER(assign.type) || 'copy'; var tagName = (assignType=='copy'? 'xg:CopyNode' : 'xg:MapNode'); var contextNode = (assign.GetSourceNodeFullName() || null); de.setRelativeNode(contextNode); var props = {sourceNode:assign.from,targetNode:assign.to}; if (assign.selectMode && assign.selectMode != 'all') props.selectMode = assign.selectMode; if (assign.guard && assign.guard+'' != 'true') { var guard = compiler.parseExpr(assign.guard,'Boolean',assign,'guard',holder,'Guard condition'); if (guard !== null) props.guard = guard; } out.beginTag(tagName,props); var nodeAssignArr = []; for (var a in assign.assigns) { var childAssign = assign.assigns[a]; if (ISA(childAssign,'gml2:NodeAssign')) nodeAssignArr.push(childAssign); else { if (assignType == 'copy') continue; printFieldAssign(childAssign); } } for (var i=0 ; i < nodeAssignArr.length ; i++) printNodeAssign(nodeAssignArr[i]); out.endTag(); } function printFieldAssign(assign) { if (ISA(holder,'gml2:SwitchOp')) out.addTag('xg:Assign',{field:assign.to,value:assign.from}); else { var val = compiler.parseExpr(assign.from,assign.exprType,assign,'from',holder,'Mapping'); if (val !== null) out.addTag('xg:Assign',{field:assign.to,value:val}); } } } XglCompiler.prototype.skipCopyStep = function(link) { var skip = true; var guard = link.guard && link.guard+''!='true'; var select = link.selectMode && link.selectMode!='all'; if (guard || select) skip = false; return skip; } XglCompiler.prototype.isShapeHolder = function(elem) { if (ISA(elem,'gml2:IShapeTransform')) return true; else if (ISA(elem,'gml2:IValueTransform')) { var predecessor = elem.getPredecessor(); var infoshape = (predecessor && ISA(predecessor,'gml2:DataBoundInteractor')? predecessor.getInfoshape() : null); return ISA(infoshape,'gml2:Cluster'); } else if (ISA(elem,'gml2:OPPlugIn')) { var predecessor = this.getPlugPredecessor(elem); var infoshape = (predecessor && ISA(predecessor,'gml2:DataBoundInteractor')? predecessor.getInfoshape() : null); return ISA(infoshape,'gml2:Cluster') && ISA(elem.parent,'gml2:IShapeTransform'); } return true; } XglCompiler.prototype.getPlugPredecessor = function(plug) { var link = null; for (var l in plug.links) { link = plug.links[l]; break; } if (!link) return null; var predecessor = link.source && link.source.parent || null; return (predecessor && predecessor.isa('#NS[PComponentUsage]')? link.source : predecessor); } XglCompiler.prototype.validateResults = function(results,elem) { var out = this.out; if (results.warnings) { var warnings = results.warnings; if (typeof warnings == 'string') { out.warning(warnings,elem); } var warnNum = warnings.length || 0; if (warnNum > 0) { for (var i=0; i 0) { for (var i=0; i