go to post Vitaliy Serdtsev · Jun 14, 2018 Suppose there is such a code: int caseSwitch = 1; switch (caseSwitch) { case 1: Console.WriteLine("Case 1"); //a lot of code break; case 2: case 8-9: Console.WriteLine("Case 2 or 8 or 9"); //a lot of code break; case 3: Console.WriteLine("Case 3"); //a lot of code break; /*... a lot conditions ...*/ default: Console.WriteLine("Default case"); //a lot of code break; }In this case $select;if/elseif/else is not effective because for last conditions will have to iterate through all the previous ones $case is redundant: you will have to specify the same code multiple times for different values For this particular case, I suggest using a transition table, for example: ClassMethod Test(caseSwitch = 3) [ ProcedureBlock = 0 ] { s:'$d(^||addr) ^||addr(1)=1, (^(2),^(8),^(9))=289, ^(3)=3 d @("case"_$g(^||addr(caseSwitch),"def")) q case1 w "Case 1" q case289 w "Case 2 or 8 or 9" q case3 w "Case 3" q casedef w "Default case" q }Of course, you can modify the example to call procedures, functions, class methods, etc.
go to post Vitaliy Serdtsev · Jun 14, 2018 I.e. you need Callback methods for Studio, Atelier, etc.? for Studio: Extending Studio (OnBeforeCompile, OnBeforeClassCompile, OnBeforeAllClassCompile, etc.) for Atelier: %Atelier.SourceControl (OnBeforeCompile, OnBeforeClassCompile, OnBeforeAllClassCompile, etc.)
go to post Vitaliy Serdtsev · Jun 14, 2018 And if so? Class dc.EmbedObj Extends %SerialObject { Property pOID As %ObjectIdentity [ Private ]; Property a As %String; Property b As %String [ Calculated, SqlComputeCode = {s {*}=##class(dc.EmbedObj).Calcb({pOID})}, SqlComputed ]; ClassMethod Calcb(pOID) As %String { s r="" q:pOID="" r s $lb(id,cls)=$lfs(pOID,"@") s p=$system.OBJ.OpenId(cls,id) q:'$IsObject(p) r i cls="dc.ContainerObj" { s r="b"_p.Foobar }elseif cls="dc.blablablaContainerObj" { s r="b"_p.qwe } q r } } Class dc.ContainerObj Extends %Persistent { Property Foobar As %String; Property InnerObj As dc.EmbedObj; Trigger NewTrigger1 [ Event = INSERT, Foreach = row/object, Time = AFTER ] { n oid s oid={%%ID}_"@"_{%%CLASSNAMEQ} &sql(update dc.ContainerObj set InnerObj_pOID=:oid where %ID=:{id}) } /// d ##class(dc.ContainerObj).Test() ClassMethod Test() { d ..%KillExtent() s t=..%New() s t.Foobar="foobar1" s t.InnerObj.a="a1" d t.%Save() &sql(insert into dc.ContainerObj(Foobar,InnerObj_a) values('foobar2','a2')) d ##class(%SQL.Statement).%ExecDirect(,"select * from dc.ContainerObj").%Display() } }
go to post Vitaliy Serdtsev · Jun 13, 2018 For serial class, I'm afraid that's not possible because of its nature. $this, $classname, etc. in the context of EmbedObj don't know anything about ContainerObj. Use bidirectional Relationship.
go to post Vitaliy Serdtsev · Jun 13, 2018 Yes, of course: Projection of Packages to Schemas Relational View of Object Features
go to post Vitaliy Serdtsev · Jun 13, 2018 You can change the XSLFO Stylesheet dynamically or statically. See XSLFOSTYLESHEET So, there is a class-report, for example MyApp.ReportDemo. Series of steps: remove option XSLFOSTYLESHEET, if any, and recompile class generate XSLFO Stylesheet: SAMPLES>d $system.OBJ.DisplayError(##class(MyApp.ReportDemo).GenerateToFile($system.CSP.GetFileName($system.CSP.GetDefaultApp($zu(5))_"/MyApp.ReportDemo.xsl"),4)) make changes to MyApp.ReportDemo.xsl add the parameter XSLFOSTYLESHEET and recompile the class again /// If defined, this provides a reference to the external /// stylesheet to use in generating the XSL-FO (PDF) report. /// If it is not provided, a stylesheet will be generated /// from the ReportDisplay XData block. Parameter XSLFOSTYLESHEET As String = "MyApp.ReportDemo.xsl"; Now open the report in your browser/command line/etc. Profit! Important: if you change something in ReportDisplay, you need to repeat the steps again.
go to post Vitaliy Serdtsev · Jun 12, 2018 Page numbering in Roman Numerals Need add the attribute format to the element <fo:page-sequence>, i.e. <fo:page-sequence master-reference='blablabla' format ='I' .. >Possible value format: format="1" results in 1 2 3 . . format="01" results in 01 02 03 format="a" results in a b c . . format="A" results in A B C. . format="i" results in i ii iii iv . . format="I" results in I II III IV . . more.. Example: Do all the steps according to Zen Report Tutorial Insert the page number into <pagefooter> <!-- Optional Pagefooter element. Does not apply in HTML output. --> <pagefooter> <item special="page-number"/> </pagefooter> Insert the following code into the class: ClassMethod ReplaceStream( ByRef stream As %Stream.TmpBinary, format) [ Private ] { s tmp=##class(%Stream.TmpBinary).%New() while 'stream.AtEnd { d tmp.Write($replace(stream.Read($$$MaxLocalLength),"<fo:page-sequence ",$$$FormatText("<fo:page-sequence format=%1 ",$$$quote(format)))) } d stream.CopyFrom(tmp) } /// d ##class(MyApp.ReportDemo).Test() ClassMethod Test(format = "1") { /* •0 = XML •1 = HTML •2 = PDF •3 = ToHTML Stylesheet •4 = ToXSLFO Stylesheet •5 = XSD Schema •6 = PrintPS •7 = Excel •8 = XSLFO •9 = ToEXCEL •10=xlsx •11=TIFF •12=pdfprint •13=displayxlsx •14=fo2pdf •15=foandpdf */ s xslfo=##class(%Stream.TmpBinary).%New() s t=..%New() d t.GenerateReportToStream(.xslfo,4) d ..ReplaceStream(.xslfo,format) s t.toxslfostream=xslfo d $system.OBJ.DisplayError(t.GenerateReport("c:\temp\test.pdf",2)) } SAMPLES>d ##class(MyApp.ReportDemo).Test("I") or SAMPLES>d ##class(MyApp.ReportDemo).Test("01") or SAMPLES>d ##class(MyApp.ReportDemo).Test("A") open test.pdf. Profit!
go to post Vitaliy Serdtsev · Jun 6, 2018 Yes, this (Classmethod Public) is only necessary for the second example.
go to post Vitaliy Serdtsev · Jun 6, 2018 Choose to your taste: Class dc.test [ Abstract ] { ClassMethod Public() [ Internal, Private, ProcedureBlock = 0 ] { q Choice0() q "Sunday" Choice1() q "Monday" Choice2() q "Tuesday" Choice3() q "Wednesday" Choice4() q "Thursday" Choice5() q "Friday" Choice6() q "Saturday" Choice() set a="entry " _"error" return a } /// d ##class(dc.test).Test() ClassMethod Test() { s daynum=$zd($h,10) w "1) ",$case(daynum, 0:$$Choice0, 1:$$Choice1, 2:$$Choice2, 3:$$Choice3, 4:$$Choice4, 5:$$Choice5, 6:$$Choice6, :$$Choice),! w "2) ",@("$$Choice"_$case(daynum, 0:0, 1:1, 2:2, 3:3, 4:4, 5:5, 6:6, :"")),! s daynum="-" w "3) ",$case(daynum, 0:"Sunday", 1:"Monday", 2:"Tuesday", 3:"Wednesday", 4:"Thursday", 5:"Friday", 6:"Saturday", :$xecute("()"_ " set a=""entry "" _""error"""_ " return a")),! } }
go to post Vitaliy Serdtsev · Jun 4, 2018 Here is my solution, which has a number of advantages: there are no restrictions to the order of ID you can search in queries for the entire timestamp or for parts of it standard, reliable and proven Caché features are used this works very, very fast. See my article for details: Indexing of non-atomic attributes Class dc.TSOrder Extends (%Persistent, %Populate) { Index Extent [ Extent, Type = bitmap ]; Index iSmartTS On (TS(KEYS), TS(ELEMENTS)); Index iTS On TS; Property TS As %TimeStamp(MAXVAL = "2016-07-31 23:59:59.999999", MINVAL = "2016-07-01 00:00:00.000000"); Property Data As %String(MAXLEN = 200, MINLEN = 100); ClassMethod TSBuildValueArray( value, ByRef array) As %Status { i value="" { s array(0)=value }else{ s date=$p(value," ",1), time=$p(value," ",2), array("date")=date, array("time")=time, array("ddhh")=$p(date,"-",3)_"-"_$p(time,":",1) } q $$$OK } /// d ##class(dc.TSOrder).Fill() ClassMethod Fill(N = {30e6}) { d ..%KillExtent(), ..Populate(N), $system.SQL.TuneTable($classname(),$$$YES), $system.OBJ.Compile($classname(),"cu-d") } }Results from SMP: select distinct null from dc.TSOrder where TS between {ts '2016-07-01 00:00:00.00000'} AND {ts '2016-07-01 23:59:59.999999'} Performance: 2.339 seconds 2109755 global references 14768692 lines executed (the number of selected records is 968476, used the normal index) select distinct null from dc.TSOrder where for some %element(TS) (%key='date' and %value = '2016-07-01') Performance: 2.269 seconds 1936962 global references 15496098 lines executed (the number of selected records is 968476, used the "smart" index) select distinct null from dc.TSOrder where for some %element(TS) (%key='ddhh' and %value = '01-13') Performance: 0.096 seconds 80488 global references 644270 lines executed (the number of selected records is 40239, used the "smart" index)
go to post Vitaliy Serdtsev · May 28, 2018 Try so: <tabGroup ... onshowTab="zenThis.refreshContents(true);"> </tabGroup>
go to post Vitaliy Serdtsev · May 11, 2018 You can see the code examples and coding style in the sources of namespaces '%SYS' and/or 'SAMPLES'. But keep in mind that the style of classes written a long time ago differs significantly from style of classes written relatively recently, ex. [$ZT vs try/catch] or [%ResultSet vs %SQL.Statement]
go to post Vitaliy Serdtsev · May 11, 2018 For self - education is the best - documentation, for example: Introduction to Caché Caché Programming Orientation Guide ObjectScript Tutorial Caché QuickStart Tutorial General System Limits Identifier Length Considerations and etc.
go to post Vitaliy Serdtsev · May 10, 2018 Localization in Caché DBMS Simple example: Class dc.test Extends %ZEN.Component.page { Parameter DOMAIN = "DCTEST"; XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ] { <page xmlns="http://www.intersystems.com/zen"> <radioSet id="lng" label="Текущий язык" layout="vertical" displayList="Португальский,Русский" valueList="pt-br,ru" value="ru" onchange="zenPage.changeLang(zenThis.value);" /> <form> <text label="Описание" required="true" requiredMessage="обязательно." /> <submit caption="Сохранить"/> </form> </page> } /// User clicked to change preferred language. ClientMethod changeLang(lng) [ Language = javascript ] { var ok = this.SrvChangeLang(lng); self.document.location.reload(); } /// Change preferred language for this session and page ClassMethod SrvChangeLang(lng) As %Boolean [ ZenMethod ] { s %session.Language=lng s %response.Language=lng q $$$YES } Method %OnAfterCreatePage() As %Status { d ..%SetValueById("lng",%session.Language) Quit $$$OK } } USER>d ##class(%MessageDictionary).ExportDomainList("messages_ru.xml","DCTEST","ru") Result (messages_ru.xml): <?xml version="1.0" encoding="UTF-8"?> <MsgFile Language="ru"> <MsgDomain Domain="DCTEST"> <Message Id="358179803">Текущий язык</Message> <Message Id="1805419696">Португальский,Русский</Message> <Message Id="2153752096">Описание</Message> <Message Id="2835101332">обязательно.</Message> <Message Id="3683485237">Сохранить</Message> </MsgDomain> </MsgFile> messages_pt-br.xml: <?xml version="1.0" encoding="UTF-8"?> <MsgFile Language="pt-br"> <MsgDomain Domain="DCTEST"> <Message Id="358179803">Idioma atual</Message> <Message Id="1805419696">Português,Russo</Message> <Message Id="2153752096">Descrição</Message> <Message Id="2835101332">é obrigatório.</Message> <Message Id="3683485237">Salvar</Message> </MsgDomain> </MsgFile> USER>d ##class(%MessageDictionary).Import("messages_pt-br.xml") Profit!
go to post Vitaliy Serdtsev · May 8, 2018 HOWTO: DER vs. CRT vs. CER vs. PEM Certificates and How To Convert Them
go to post Vitaliy Serdtsev · May 7, 2018 USER>w $zv Cache for Windows (x86-32) 2015.2 (Build 664_3U) Wed Aug 12 2015 12:29:34 EDTThe date is saved to the database correctly. Class dc.A Extends %Persistent { Property DOB As %Date; } Class dc.MVC.A Extends %ZEN.DataModel.ObjectDataModel { Property DOB As %Date(ZENATTRS = "id:DOB|format:DMY|separator:/", ZENCONTROL = "dateText"); Method %OnNewSource(Output pSC As %Status = {$$$OK}) As %RegisteredObject { q ##class(dc.A).%New() } Method %OnOpenSource( pID As %String, pConcurrency As %Integer = -1, Output pSC As %Status = {$$$OK}) As %RegisteredObject { q ##class(dc.A).%OpenId(pID,pConcurrency,.pSC) } Method %OnSaveSource(pSource As dc.A) As %Status { q pSource.%Save() } ClassMethod %OnDeleteSource(pID As %String) As %Status { q ##class(dc.A).%DeleteId(pID) } Method %OnLoadModel(pSource As dc.A) As %Status { s ..DOB = pSource.DOB q $$$OK } Method %OnStoreModel(pSource As dc.A) As %Status { s pSource.DOB = ..DOB q $$$OK } } Class dc.test Extends %ZEN.Component.page { XData Contents [ XMLNamespace = "http://www.intersystems.com/zen" ] { <page xmlns="http://www.intersystems.com/zen"> <dataController id="a-controller" modelClass="dc.MVC.A" modelId=""/> <dynaForm id="a-form" controllerId="a-controller"/> <button caption="Save" onclick="zen('a-form').save();" /> </page> } }