Skip to content

Instantly share code, notes, and snippets.

@daimor
Created May 18, 2014 20:24
Show Gist options
  • Save daimor/3923810dcd60126647b7 to your computer and use it in GitHub Desktop.
Save daimor/3923810dcd60126647b7 to your computer and use it in GitHub Desktop.
Caché JavaScript Routine
<?xml version="1.0" encoding="UTF-8"?>
<Export generator="Cache" version="25" zv="Cache for UNIX (SUSE Linux Enterprise Server for x86-64) 2014.1 (Build 608U)" ts="2014-05-19 00:22:31">
<Class name="%CJS.RoutineWizard">
<Description><![CDATA[
Studio Template:<br>
Create a new Cache JavaScript Routine.]]></Description>
<StorageStrategy/>
<Super>%ZEN.Template.studioTemplate</Super>
<TimeChanged>63325,86382.045933</TimeChanged>
<TimeCreated>63325,65834.566957</TimeCreated>
<Parameter name="TEMPLATENAME">
<Default>Cache JavaScript</Default>
</Parameter>
<Parameter name="TEMPLATETITLE">
<Default>Cache JavaScript</Default>
</Parameter>
<Parameter name="TEMPLATEDESCRIPTION">
<Default>Create a new Cache JavaScript routine.</Default>
</Parameter>
<Parameter name="TEMPLATETYPE">
<Default>CJS</Default>
</Parameter>
<Parameter name="TEMPLATEMODE">
<Description>
What type of template.</Description>
<Default>new</Default>
</Parameter>
<Parameter name="TEMPLATEGROUP">
<Description>
If this is a TEMPLATEMODE="new" then this is the name of the tab
in Studio this template is dispayed on. If none specified then
it displays on 'Custom' tab.</Description>
<Type>STRING</Type>
</Parameter>
<XData name="templateBody">
<Description>
This XML block defines the contents of the body pane of this Studio Template.</Description>
<XMLNamespace>http://www.intersystems.com/zen</XMLNamespace>
<Data><![CDATA[
<pane id="body">
<vgroup labelPosition="left" cellStyle="padding: 2px; padding-left: 5px; padding-right: 5px;">
<html id="desc" OnDrawContent="%GetDescHTML"/>
<text label="Routine Name:"
id="ctrlRoutineName"
name="RoutineName"
size="40"
required="true"
labelClass="zenRequired"
title="Cache JavaScript Routine name"
onchange="zenPage.updateState();"
/>
</vgroup>
</pane>
]]></Data>
</XData>
<Method name="%GetDescHTML">
<Description>
Provide contents of description component.</Description>
<FormalSpec>pSeed:%String</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[ Quit $$$OK
]]></Implementation>
</Method>
<Method name="onstartHandler">
<Description>
This is called when the template is first displayed;
This provides a chance to set focus etc.</Description>
<Language>javascript</Language>
<ClientMethod>1</ClientMethod>
<Implementation><![CDATA[
// give focus to name
var ctrl = zenPage.getComponentById('ctrlRoutineName');
if (ctrl) {
ctrl.focus();
ctrl.select();
}
]]></Implementation>
</Method>
<Method name="formValidationHandler">
<Description>
Validation handler for form built-into template.</Description>
<Language>javascript</Language>
<ClientMethod>1</ClientMethod>
<Implementation><![CDATA[
var rtnName = zenPage.getComponentById('ctrlRoutineName').getValue();
if ('' == rtnName) {
return false;
}
return true;
]]></Implementation>
</Method>
<Method name="%OnTemplateAction">
<Description>
This method is called when the template is complete. Any
output to the principal device is returned to the Studio.</Description>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set tRoutineName = ..%GetValueByName("RoutineName")
Set %session.Data("Template","NAME") = tRoutineName_".CJS"
Write "// "_tRoutineName,!
Quit $$$OK
]]></Implementation>
</Method>
</Class>
<Class name="%CJS.StudioRoutines">
<StorageStrategy/>
<Super>%Studio.AbstractDocument</Super>
<TimeChanged>63326,278.847507</TimeChanged>
<TimeCreated>63325,463.418569</TimeCreated>
<Projection name="RegisterExtension">
<Description>
The extension name, this can be a comma separated list of extensions if this class supports more than one</Description>
<Type>%Projection.StudioDocument</Type>
<Parameter name="DocumentDescription" value="CachéJavaScript Routine"/>
<Parameter name="DocumentExtension" value="cjs"/>
<Parameter name="DocumentIcon" value="1"/>
<Parameter name="DocumentType" value="JS"/>
</Projection>
<Property name="ShortName">
<Type>%String</Type>
</Property>
<Method name="%OnNew">
<Description>
Set the name property</Description>
<FormalSpec>name:%String</FormalSpec>
<Private>1</Private>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
set ..ShortName=$piece(name,".",1,$length(name,".")-1)
set tSC=##super(name)
if $$$ISERR(tSC) Quit tSC
quit $$$OK
]]></Implementation>
</Method>
<Method name="Load">
<Description>
Load the routine in Name into the stream Code</Description>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
set source=..Code
do source.Clear()
set pCodeGN=$name(^rCJS(..ShortName,0))
for pLine=1:1:$get(@pCodeGN@(0),0) {
do source.WriteLine(@pCodeGN@(pLine))
}
do source.Rewind()
Quit $$$OK
]]></Implementation>
</Method>
<Method name="CompileDocument">
<Description>
CompileDocument is called when the document is to be compiled
It has already called the source control hooks at this point</Description>
<FormalSpec><![CDATA[&qstruct:%String]]></FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Write !,"Compile: ",..Name
Set compiledCode=##class(%Routine).%OpenId(..ShortName_".INT")
Set compiledCode.Generated=1
do compiledCode.Clear()
do compiledCode.WriteLine(" ;generated at "_$zdatetime($ztimestamp,3))
do ..GenerateIntCode(compiledCode)
do compiledCode.%Save()
do compiledCode.Compile()
Quit $$$OK
]]></Implementation>
</Method>
<Method name="GenerateIntCode">
<Internal>1</Internal>
<FormalSpec>aCode</FormalSpec>
<Implementation><![CDATA[
set varMatcher=##class(%Regex.Matcher).%New("[ \t]*(var[ \t]+)?(\w[\w\d]*)[ \t]*(\=[ \t]*(.*))?")
set printlnMatcher=##class(%Regex.Matcher).%New("[ \t]*(?:console\.log|println)\(([^\)]+)\)?")
set readMatcher=##class(%Regex.Matcher).%New("[ \t]*read\((.*)\,(.*)\)")
set source=..Code
do source.Rewind()
while 'source.AtEnd {
set tLine=source.ReadLine()
set pos=1
while $locate(tLine,"(([^\'\""\;\r\n]|[\'\""][^\'\""]*[\'\""])+)",pos,pos,tCode) {
set tPos=1
if $zstrip(tCode,"*W")="" {
do aCode.WriteLine(tCode)
continue
}
if varMatcher.Match(tCode) {
set varName=varMatcher.Group(2)
if varMatcher.Group(1)'="" {
do aCode.WriteLine($char(9)_"new "_varName)
}
if varMatcher.Group(3)'="" {
set expr=varMatcher.Group(4)
set expr=..Expression(expr)
do:expr'="" aCode.WriteLine($char(9)_"set "_varName_" = "_expr)
}
continue
} elseif printlnMatcher.Match(tCode) {
set expr=printlnMatcher.Group(1)
set expr=..Expression(expr)
do:expr'="" aCode.WriteLine($char(9)_"Write "_expr_",!")
} elseif readMatcher.Match(tCode) {
set expr=readMatcher.Group(1)
set expr=..Expression(expr)
set var=readMatcher.Group(2)
do:expr'="" aCode.WriteLine($char(9)_"read "_expr_","_var_",!")
}
}
}
]]></Implementation>
</Method>
<Method name="Expression">
<ClassMethod>1</ClassMethod>
<FormalSpec>tExpr</FormalSpec>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
set matchers($increment(matchers),"matcher")="(?sm)([^\'\""]*)\+[ \t]*(?:\""([^\""]*)\""|\'([^\']*)\')([^\'\""]*)"
set matchers(matchers,"replacement")="$1_""$2$3""$4"
set matchers($increment(matchers),"matcher")="(?sm)([^\'\""]*)(?:\""([^\""]*)\""|\'([^\']*)\')[ \t]*\+([^\'\""]*)"
set matchers(matchers,"replacement")="$1""$2$3""_$4"
set matchers($increment(matchers),"matcher")="(?sm)([^\'\""]*)(?:\""([^\""]*)\""|\'([^\']*)\')([^\'\""]*)"
set matchers(matchers,"replacement")="$1""$2$3""$4"
set tResult=tExpr
for i=1:1:matchers {
set matcher=##class(%Regex.Matcher).%New(matchers(i,"matcher"))
set replacement=$get(matchers(i,"replacement"))
set matcher.Text=tResult
set tResult=matcher.ReplaceAll(replacement)
}
quit tResult
]]></Implementation>
</Method>
<Method name="Delete">
<Description>
Delete the routine 'name' which includes the routine extension</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>name:%String</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set rtnName = $piece(name,".",1,$length(name,".")-1)
Kill ^rCJS(rtnName)
Quit $$$OK
]]></Implementation>
</Method>
<Method name="Lock">
<Description>
Lock the current routine, default method just unlocks the ^rCJS global with the name of the routine.
If it fails then return a status code of the error, otherise return $$$OK</Description>
<FormalSpec>flags:%String</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Lock +^rCJS(..Name):0 Else Quit $$$ERROR($$$CanNotLockRoutine,..Name)
Quit $$$OK
]]></Implementation>
</Method>
<Method name="Unlock">
<Description>
Unlock the current routine, default method just unlocks the ^rCJS global with the name of the routine</Description>
<FormalSpec>flags:%String</FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Lock -^rCJS(..Name)
Quit $$$OK
]]></Implementation>
</Method>
<Method name="Save">
<Description>
Save the routine stored in Code</Description>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
set ^rCJS(..ShortName,"LANG")="CJS"
set pCodeGN=$name(^rCJS(..ShortName,0))
kill @pCodeGN
set @pCodeGN=$ztimestamp
Set ..Code.LineTerminator=$char(13,10)
set source=..Code
do source.Rewind()
WHILE '(source.AtEnd) {
set pCodeLine=source.ReadLine()
set @pCodeGN@($increment(@pCodeGN@(0)))=pCodeLine
}
set @pCodeGN@("SIZE")=..Code.Size
Quit $$$OK
]]></Implementation>
</Method>
<Method name="TimeStamp">
<Description>
Return the timestamp of routine 'name' in %TimeStamp format. This is used to determine if the routine has
been updated on the server and so needs reloading from Studio. So the format should be $zdatetime($horolog,3),
or "" if the routine does not exist.</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>name:%String</FormalSpec>
<ReturnType>%TimeStamp</ReturnType>
<Implementation><![CDATA[
Set rtnName = $piece(name,".",1,$length(name,".")-1)
Set timeStamp=$zdatetime($get(^rCJS(rtnName,0)),3)
Quit timeStamp
]]></Implementation>
</Method>
<Method name="Exists">
<Description>
Return 1 if the routine 'name' exists and 0 if it does not.</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>name:%String</FormalSpec>
<ReturnType>%Boolean</ReturnType>
<Implementation><![CDATA[
Set rtnName = $piece(name,".",1,$length(name,".")-1)
Set rtnNameExt = $piece(name,".",$length(name,"."))
Quit $data(^rCJS(rtnName))&&($get(^rCJS(rtnName,"LANG"))=$zconvert(rtnNameExt,"U"))
]]></Implementation>
</Method>
<Method name="ListExecute">
<ClassMethod>1</ClassMethod>
<FormalSpec><![CDATA[&qHandle:%Binary,Directory:%String,Flat:%Boolean,System:%Boolean]]></FormalSpec>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set qHandle=$listbuild(Directory,Flat,System,"")
Quit $$$OK
]]></Implementation>
</Method>
<Method name="ListFetch">
<Description><![CDATA[
This should return a Row in the form:<br>
$listbuild(name,date/time modified,size,directory delimitor)<ul>
<li>name - The name to display in the open dialog</li>
<li>date/time modified - In %TimeStamp format the date/time this item was last modified</li>
<li>size - The size of this item</li>
<li>directory delimitor - If this is not an directory then return "" here, if it is a directory then
return the type of delimitor to use when they double click on this directory</li>]]></Description>
<ClassMethod>1</ClassMethod>
<FormalSpec><![CDATA[&qHandle:%Binary,&Row:%List,&AtEnd:%Integer=0]]></FormalSpec>
<PlaceAfter>ListExecute</PlaceAfter>
<ReturnType>%Status</ReturnType>
<Implementation><![CDATA[
Set Row="",AtEnd=0
If qHandle="" Set AtEnd=1 Quit $$$OK
If $list(qHandle)'=""||($list(qHandle,4)=1) Set AtEnd=1 Quit $$$OK
set AtEnd=1
Set rtnName=$listget(qHandle,5)
For {
Set rtnName=$order(^rCJS(rtnName)) Quit:rtnName=""
continue:$get(^rCJS(rtnName,"LANG"))'="CJS"
set timeStamp=$zdatetime($get(^rCJS(rtnName,0)),3)
set size=+$get(^rCJS(rtnName,0,"SIZE"))
Set Row=$listbuild(rtnName_".cjs",timeStamp,size,"")
set AtEnd=0
set $list(qHandle,5)=rtnName
Quit
}
Quit $$$OK
]]></Implementation>
</Method>
<Method name="GetOther">
<Description>
Return other document types that this is related to.
Passed a name and you return a comma separated list of the other documents it is related to
or "" if it is not related to anything. Note that this can be passed a document of another type
for example if your 'test.XXX' document creates a 'test.INT' routine then it will also be called
with 'test.INT' so you can return 'test.XXX' to complete the cycle.</Description>
<ClassMethod>1</ClassMethod>
<FormalSpec>Name:%String</FormalSpec>
<ReturnType>%String</ReturnType>
<Implementation><![CDATA[
Set rtnName = $piece(Name,".",1,$length(Name,".")-1)_".INT"
Quit:##class(%Routine).%ExistsId(rtnName) rtnName
Quit ""
]]></Implementation>
</Method>
<Query name="List">
<Description><![CDATA[
This query scans over the documents for the Studio open dialog.
The arguments are defined in <method>ItemList</method>.<p>
This should return a row form by:<br>
$listbuild(name,date/time modified,size,directory delimitor)
<ul>
<li>name - The name to display in the open dialog</li>
<li>date/time modified - In %TimeStamp format the date/time this item was last modified</li>
<li>size - The size of this item</li>
<li>directory delimitor - If this is not an directory then return "" here, if it is a directory then
return the type of delimitor to use when they double click on this directory</li>
</ul>]]></Description>
<Type>%Query</Type>
<FormalSpec>Directory:%String,Flat:%Boolean,System:%Boolean</FormalSpec>
<SqlProc>1</SqlProc>
<Parameter name="ROWSPEC" value="name:%String,modified:%TimeStamp,size:%Integer,directory:%String"/>
</Query>
</Class>
</Export>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment