<everything others have already said> + try to look for *.xsd files on your www.musicxml.org site
- Log in to post comments
<everything others have already said> + try to look for *.xsd files on your www.musicxml.org site
radix 10: mantisse * 10**exponent (the ISC floating format)
radix 2 : mantisse * 2 ** exponent ($double/ IEEE 754 format )
The first part is easy... string, integer,... that's not the problem.
The second part, is it a date or not depends on the date format(s) you expect (or allow).
But for the first part, you can use this approach:
/// Return values
/// 0=empty, 1=string, 2=integer, 3=float/radix-10, 4=float/radix-2, 5=object
ClassMethod ValType(var)
{
if var="" quit 0
if $isobject(var) quit 5
quit $select($length(var)>254:1, 1:$translate($ascii($listbuild(var),2),1245678,1122334))
}Of course, hardcore people would use just one line
ClassMethod ValType(var) { q $s(var="":0, $isobject(var):5, $l(var)>254:1, 1:$tr($a($lb(var),2),1245678,1122334)) }Just to bring things in the right light
I'm a retired person but one needs some level of activity, that's the reason, why I'm here, do give answers and comments (and if the old customers need "a kind of prolonged help", I'm there too).
In early and mid seventies I programmed some so called "desktop computer", learned Cobol, IBM/360 assembler, Algol60 and Pascal as the preferred language on the university. Then, end of 1977 I met M (DEC's V4B).
Until the nineties thre were no IDEs, the first one I used was Serenji (from GeorgeJames) for MSM and Cache's Studio (with a lovely meat-chopper as the compiler icon). And there were no GitHub.
Anyway, we had great projects and great programms and fun.
The above means, I for myself do not need anything, neither Atelier nor VS-Code not even Studio but in case, I want to edit a class or routine, I prefer Studio.
During my active times, Studio was a great editor (and still it is!), sometimes I had more then one Studio open (at the same time, of course) to different Servers or different namespaces that's the reason why I requested the feature (server defined colors) some decades ago. The light red was the connection into, say a productio system, the green was into a test namespace and blue, for example was the developmet system. A short glimpse at the display, if I saw red, my brain said, "keep fingers from keyboard", if I saw blue then my brain was ready for switch off...
But I know several people working since decades with Studio only (and with the line editor before - I hope you know ^% and remember it?). Those people are (roughly) between 50 and 60 years old, worked (and still work) with whatever brand of M-Language (DTM, MSM, ISM, GT-M, Cache etc.) and never had contact to "modern" languages like java, C++, javascript, etc.
That's in my opinion the reason, why Atelier not so widespread as it deserved to be.
De facto, we have a two class society of M-programers
a) the young ones,
- they know everything about the current IDEs (Visual Studio, VS-Code, Eclipse, etc.
- they try to master (more or less) the M-World but
- their heart beats for languages as Java, Javascript, C++, Angular, Scala, etc.
- can't live without Git, GitHub, Bitbucket etc.
- they do not understand the essence/character of M-language (especially Cache/Iris)
- and think, MongoDB is the only NoSql-DB
- work few months (or one or two years) for a company, then change
- in the new company start over with another environment (Java, Angular, whatever)
- many are, I use to say, single-threaded: one project at time only
- etc.
b) and the old ones
- they grew up with the M-language
- they understand the power of M as a unity (language and database)
- most of them never used Git (and similar sites) for version control
- some of them never used a version control at all!
- most of them work with Windows (but this has historical reason)
- a few years before retirement there's no incentive to change to new IDEs
The real problem is not which IDE is in use, the real problem is to get people for M-programming, who then use an IDE. There are, I think, more old(er) then young M-Programer. I know for companies, they search for M-Programers but have dufficulties to find one.
That said, at the end of the day, you have to raise interesse for M-Language and M-Database. So you will need another means and not just a new IDE.
Maybe I'm wrong, but it's like comparing the M-Language and M-Database with a dinner by a start chef.
Nobody asks for the IDE they was in use, nobody asks for the pots and stoves they was in use.
After you leave the restaurant, the only thing that remains is, was the dinner good, were you satisfied.
Same goes the M-Language, does it can all things I need, will I be happy with it.
And yes, my answer is a big yes, definitive.
In my opinion the very first question is the support. a) Studio
The current situation with VS-Code and the COS-plugin (my very private opinion) is
ad 1): assume, one day ISC says "VS-Code with COS plugin exists, so we can drop Studio". What should happen to all those COS-programers, how should they master VS-Code? Most of them have never ever heard about VS-Code? Keep in mind, not everybody grew up with mother's breast in one hand and an App in another !
ad 2): yes, there are some YouTube videos. On all videos I saw, VC-Code was already installed
Do not get me wrong, I'm not again VS-Code (the truth is, I would like to use it on my Linux) and I'm not for keeping Studio until eternity (because there is no Studio for Linux). But currently, Studio has some advantage (again, for me):
In case, you want some speed, use
set outArray = []instead of
set outArray = ##class(%DynamicArray).%New()Your speed gain: ca. 50%
The %OpenId() method checks, if the object to be opened ALREADY open (in the current session/job). If it's open then it just returns with an success. In other case, it loads it from the disk.
If on your development system, for whatever reason, there is an open instance then you save 6.1 million times the "load" operation.
You are wondering about a SLOW production server and a FAST development machine?
I show you, how to turn your machines (production or development or both) into a SLOW and FAST systems by using your own measurement method.
ClassMethod Unclean()
{
s p=##class(digi.packet).%OpenId("packet||5237")
d ..runme4()
}
ClassMethod Clean()
{
d ..runme4()
}Login to either of your systems and try the abowe methods in a terminal session. On my local system (of course, with an own persistent class) the one method is 12 times faster then the other.
Maybe you have an "Unclean" situation on your development system...
Also, sometime it is worth to put a line like
do $system.OBJ.ShowObjects()as a first line into the runme4() method
Why do you do make things such complicated? You neither need %ListOfDataTypes nor %ZEN.proxyObject. If I see correctly, at the end of the query you have a characterstream, filled with JSON. Right? So just create this stream on-the-fly!
set json = ##class(%Stream.TmpCharacter).%New(), del=""
&sql(declare ... )
&sql(open queryONLWK01)
do json.Write("[")
for {
&sql(fetch queryONLWK01)
quit:SQLCODE
do json.Write(del_"{")
do json.Write("""articlenumber"":" _ articlenumber _ ",") // (*)
do json.Write("""amount"":" _ amount)
do json.Write("}")
set del=","
}
do json.WriteLine("]")
(*) if articlenumber is an alphanumeric value then you should do something like this
do json.Write("""Aarticlenumber"":"_$$json(article)_",") where $$json(x) could be something like this ($zconvert() has no JSON-mode in Cache-2013)
json(val) {
for c="\","/","""",$c(8),$c(9),$c(10),$c(12),$c(13) set val=$replace(val,c,"\"_$tr(c,$c(8,9,10,12,13),"btnfr"))
for quit:'$locate(val,"[:cntrl:]",0,j,v) set $e(val,j-1)="\u"_$e($zh($a(v)+65536),2,5)
quit """"_$zcvt(val,"O","UTF8")_""""
}OK, I installed VSCode together with the objectscript extension on my Linux. Now, I would like to play a little bit with this IDE, merlely for an VSCode beginner it's somewhat difficult. According to https://openexchange.intersystems.com/package/VSCode-ObjectScript there is a settings file, ".vscode/settings.json", to make a connection to my iris server... I located a file ".config/Code/User/settings.json". After entering the connection info -this works now. Question, how or where can I enter a second (or even more) Cache/Iris servers? Next, created a short test routine and saved, but it's not compiled. How to compile it?
I have never used VSCode before, I work since beginning with the Cache-Studio (this means some 20 years or so) and other twenty years before with other editors. Is there somewhere a short tutorial or some other info? It seems, I will need some time to catch this "modern" stuff ;-)
Thank you.
You could try this way:
Class My.Table2 Extends %Persistent
{
Property Name As %String;
Property Age As %Numeric;
Property City As %String;
Property Phone As %String;
ClassMethod Test()
{
// This is your Data-Object...
set data=[]
do data.%Push({"Name":"Joe", "Age":44, "City":"Boston", "Phone":"1-234-4567"})
do data.%Push({"Name":"Ron", "Age":48, "City":"Dallas", "Phone":"1-234-5678"})
do data.%Push({"Name":"Eve", "Age":40, "City":"Miami", "Phone":"1-234-4567"})
do data.%Push($lb("Tommy", 50, "New York", "1-345-6789"))
do data.%Push($lb("Alexa", 35, "Portland", "1-567-8901"))
// Now insert all the above data into your table...
if 'data.%Size() quit
set cnt=0, size=data.%Size()
while $i(cnt)<=size {
set rowData=data.%Get(cnt-1)
&sql(
INSERT INTO My.Table2 (Name,Age,City,Phone)
VALUES (My.Table2_DataProvider(:rowData), :row(2), :row(3), :row(4))
)
}
}
ClassMethod DataProvider(rowData) As %String [ PublicList = row, SqlProc ]
{
kill row
if $isobject(rowData) {
set it=rowData.%GetIterator()
while it.%GetNext(,.val) { set row($i(row))=val }
} else {
for i=1:1:$ll(rowData) { set row(i)=$lg(rowData,i) }
}
quit row(1)
}
Storage Default
{
<Data name="Table2DefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Name</Value>
</Value>
<Value name="3">
<Value>Age</Value>
</Value>
<Value name="4">
<Value>City</Value>
</Value>
<Value name="5">
<Value>Phone</Value>
</Value>
</Data>
<DataLocation>^My.Table2D</DataLocation>
<DefaultData>Table2DefaultData</DefaultData>
<IdLocation>^My.Table2D</IdLocation>
<IndexLocation>^My.Table2I</IndexLocation>
<StreamLocation>^My.Table2S</StreamLocation>
<Type>%Library.CacheStorage</Type>
} }
Create your data for insert and then
INSERT into yourtable (Prop1, Prop2, ...)
VALUES (sqlProcForTheFirstValue(), :localVarForOtherValues(2), :localVatForOtherValues(3),...)see the above example.
Take care of the sequence of INSERT names and row(i) values.
Oh, I just see now, I forgot to add the two test lines
Enter into browser : http://localhost:52773/csp/user/DC.Upload.cls?pswd=123&rpt=456
Enter into Terminal:
IDEV:USER>write ##class(DC.Download).GetFile(123,456,"/tmp/inpfiles/") ==> 1Sorry, but it's not clear to me what you want to achieve.
If you want to provide data if somebody connected to your server, then use the DC.Upload class (see below).
If somebody has data for you and you want to programatically download this data, use the DC.Download class (see below).
The examples below does not handle the case, where the (Cache/IRIS)Server needs an user authentication (my IRIS System > Security Management > Web Applications is set to "Unauthenticated")
Server side (Upload)
/// Upload (i.e. provide) data to a remote party
Class DC.Upload Extends %CSP.Page
{
ClassMethod OnPage() As %Status
{
if %request.Data("myData")]"" {
do %request.Data("myData").OutputToDevice()
do %request.Data("myData").%Close() }
else {
write "<html><head></head><body>",!
write "Please provide a correct Password and ReportId<br>",!
write "</body></html>",!
}
quit $$$OK
}
ClassMethod OnPreHTTP() As %Boolean [ ServerOnly = 1 ]
{
if ..chkPsw(), ..chkRpt(.file) {
set data=##class(%FileBinaryStream).%New()
set size=##class(%File).GetFileSize(file)
set name=##class(%File).GetFilename(file)
do data.LinkToFile(file)
set %response.ContentType="application/pdf"
do %response.SetHeader("Content-Disposition","attachment;filename="_name)
do %response.SetHeader("Content-Length",size)
set time=$h-1
set %response.Expires=$zd(time,11)_", "_$zd(time,2)_" 00:00:00 GMT"
set %request.Data("myData")=data
} else {
set %request.Data("myData")=""
}
quit $$$OK
}
ClassMethod chkPsw()
{
set psw=$g(%request.Data("pswd",1))
if psw]"" quit 1
quit 0
}
ClassMethod chkRpt(name)
{
set rpt=$g(%request.Data("rpt",1))
if rpt]"" {
set name="/tmp/outfiles/74LS13.pdf"
quit 1
}
quit 0
}
}
Client side (download)
/// Download (i.e. get) data from remote server
///
Class DC.Download Extends %RegisteredObject
{
ClassMethod GetFile(psw, rpt, saveTo = "/tmp/inpfiles/")
{
set http=##class(%Net.HttpRequest).%New()
set http.Server="localhost"
set http.Port=52773
do http.SetParam("pswd",psw)
do http.SetParam("rpt",rpt)
if http.Get("/csp/user/DC.Upload.cls") {
set file=$piece($g(http.HttpResponse.Headers("CONTENT-DISPOSITION")),"=",2)
set del=$select($zversion(1)=2:"\", 1:"/")
set file=saveTo_$s($e(saveTo,*)=del:"",1:del)_$s(file="":"noname.dat",1:file)
open file:"nwu":0
if $t {
use file
do http.HttpResponse.Data.OutputToDevice()
close file
quit 1
} else {
quit "0,Can't open "_file
}
} else {
quit "0,"_http.HttpResponse.StatusLine
}
}
}
Create a temp table with all properties you need, store it in a Cachte/IRIS-Temp unde $J of the running job (it could be, your applcation runs in several instances at the same time) an use it in your INSERT / UPDATE.
This is your Table
Class My.Table1 Extends %Persistent
{
Property Name As %String;
Property Age As %Numeric;
ClassMethod Test()
{
d ##class(My.Temp).%DeleteId($j)
s tmp=##class(My.Temp).%New()
s tmp.TempID=$j, tmp.Name="Paul", tmp.Age=69
d tmp.%Save()
// or popolate the My.Temp via INSERT...
&sql(INSERT INTO My.Table1 (Name,Age)
SELECT Name,Age FROM My.Temp WHERE TempID=$j
)
}
}and this is the Temporary Table
Class My.Temp Extends %Persistent
{
Parameter DEFAULTGLOBAL = "^CacheTemp.TempTable"; Property TempID As %Integer;
Property Name As %String;
Property Age As %Numeric;
Index main On TempID [ IdKey ];
}Do I understand you right, you want to get the Value of a VALUELIST as a return value of a method? If yes, then the answer is yes.
Class Some.Class
{
Property Status As %String (VALUELIST = ",1,2,3,4");
Property Rating As %String(VALUELIST = ",Bad,Good,Excellent");
/// For the Status property only
ClassMethod StatusValues() As %String [ CodeMode = objectgenerator ]
{
for i=%class.Properties.Count():-1:0 if i,%class.Properties.GetAt(i).Name="Status" quit
set val=$select(i:%class.Properties.GetAt(i).Parameters.GetAt("VALUELIST"), 1:"")
do %code.WriteLine($c(9)_"quit """_val_"""")
}
/// For all properties with a VALUELIST parameter
ClassMethod Values(prop) [ CodeMode = objectgenerator ]
{
set sel=""
for i=1:1:%class.Properties.Count() {
set val=%class.Properties.GetAt(i).Parameters.GetAt("VALUELIST")
set:val]"" sel=sel_""""_%class.Properties.GetAt(i).Name_""":"""_val_""", "
}
do %code.WriteLine($c(9)_"quit $case(prop,"_sel_":"""")")
}
}
And a few examples...
Write ##class(Some.Class).StatusValues() ==> ,1,2,3
Write ##class(Some.Class).Values("Status") ==> ,1,2,3
Write ##class(Some.Class).Values("Rating") ==> Bad,Good,Excellent
Write ##class(Some.Class).Values("OtherProperty") ==>
not a built-in, but you can easily create one
ClassMethod ParamList() [ CodeMode = objectgenerator ] As %List
{
set params=""
for i=1:1:%class.Parameters.Count() set params=params_$lb(%class.Parameters.GetAt(i).Name)
do %code.WriteLine($c(9)_"quit """_params_"""")
}
ClassMethod ParamString() As %String
{
quit $listtostring(..ParamList())
}as far as I know (subject to verification) you source code will be compiled into a p-code (pseudo- or portable-code). This means, Cache and IRIS behave (regarding program execution) as virtual machines, like the JVM (Java Virtual Machine).
$listbuild() and all other functions, like $length(), $char() etc. are (I call them) basic functions of COS and have nothing to do with objects. The language of Cache (and of course IRIS ) handles data as raw (basic) data and not as objects, like some other (but not all) languages.
For example, in JavaScript you can do
var text="Some text";
alert("'" + text + "' has "+text.length + " characters");
alert("'Some text' has " + "Some text".length + " characters");because both, a (text)variable and a (text)string have an (object)property name 'length'.
Beside the raw data type COS also has object data type and most of the standard COS functions will accept an object property as argument, for example:
Class Test.Class Extends %RegisteredObject
{
Property Data as %String;
}
set text="Some text"
set obj = ##class(Test.Class).%New()
set obj.Data = "Some text";
write $length(text),!
write $length(obj.Data),!JavaScript, as your code shows, is compiled and executed on client side (in the browser).
The part of the code #()# you use is CSP (CacheServerPages), which is compiled and prepared by the server for execution by client.
Hence, you can't use the #()# syntax in a pure JavaScript code.
$lb(data1, data2, data3, ... dataN) is built as a string of item1 item2 item3 ... itemN
itemN:= <len> <type> <dataN>assuming, you are on a little-endian CPU and
l1 = $length(data)
l2 = l1 + 1 // for type byte
l3 = l2 + 1 // for the length itselfthen the length is as follows
if l1<=253 then len: <l3>
elseif l1<=65534 len:= <0> <l2-lowbyte> <l2-highbyte>
else len:= <0> <0> <0> <l2-lowbyte-loworderword> ... <l2-highbyte-highorderword>And don't forget,
$lb(123) is not the same as $lb(1230/10), hence we have a $ls() function!
I have no idea how you did your endless loop, but the above code can't do that.
the functions $order() and $query() are your best friends ;-))
Write, for example, a method like this:
ClassMethod(ref)
{
if $data(@ref)#10 write ref,"=",@ref,! // do something with this node
set i=""
for set i=$order(@ref@(i)) quit:i="" do ..Show($name(@ref@(i)))
}So, for testdata like
set tmp(1,2,3)="Joe"
set tmp(1,2,3,4,1)="Paul"
set tmp(1,2,3,4,2)="Paula"
set tmp(1,2,3,5,6)="Tom"start some testing
do ##class(yourclass).Show($na(tmp)) // shows all entries
do ##class(yourclass).Show($na(tmp(1,2))) // also shows all entries
do ##class(yourclass).Show($na(tmp(1,2,3))) // shows Joe
do ##class(yourclass).Show($na(tmp(1,2,3,4)) // shows Paul and Paula
do ##class(yourclass).Show($na(1,2,3,5))) // shows Tom
do ##class(yourclass).Show($na(tmp(1,2,3,5,6))) // shows Tom
do ##class(yourclass).Show($na(tmp(2,3))) // shows nothing
Now, I hope, you can figure out how to get out your desired data
set x="1.2.3", y=$name(tmp)
for i=1:1:$length(x,".") { set y=$name(@y@($piece(x,".",i))) }
set @y=""
kill x,y,iYou can put al the above in one line, if you are in terminal. Or put it in a method
ClassMethod setTemp(x) [ PublicList = tmp]
{
set y=$name(tmp)
for i=1:1:$length(x,".") { set y=$name(@y@($piece(x,".",i))) }
set @y=""
} Or you take the shorthand
set x="1.2.3", @("tmp("_$tr(x,".",",")_")=""""")
But this works only as long as x contains number_period_numeber_period_...No leading zeros, no alphabetics...
Ok, I started my Studio (2018.1.1) --> New Class --> ABC.Try --> Finish.
Then removed the Extends... and I left over with
Class ABC.Try
{
}Then saved (but no compile) and my test in a terminal:
USER>s aa=##class(%Dictionary.PackageDefinition).GetPackageList()
USER>w aa.Find("ABC")
523
USER>
In the class definition one can create persistent-, serial-, registered-, abstract- and data-classes.
All of the above classes are contained in ##class(%Dictionary.PackageDefinition).GetPackageList(). Do you have a example for an class, which is not contained in the above method?
Or there is just a misunderstanding?
The simple (and documented) answer is something like this:
set name="Test.Package"
if ##class(%Dictionary.PackageDefinition).GetPackageList().Find($zconvert(name,"u")) { w "Yes" } else { w "No" }@Timothy
using ^oddDEF and/or ^oddCOM works today, we hope, it will work tomorrow too, but there is no garantie
A warning about long time open transactions will be placed in cconsole.log and alerts.log (both files in $system.Util.InstallDirectory()_"mgr" directory) - at least this is the case what I see on a customers system. The entries look like this:
04/05/19-02:31:34:470 (21012) 1 [SYSTEM MONITOR] TransOpenSecs Warning: One or more transactions open longer than 10 minutes. Process id 18624 22208 (only top 5 shown)
08/29/19-14:31:03:802 (18576) 1 [SYSTEM MONITOR] TransOpenSecs Warning: One or more transactions open longer than 10 minutes. Process id 4128 (only top 5 shown)
09/04/19-17:16:19:090 (21344) 1 [SYSTEM MONITOR] TransOpenSecs Warning: One or more transactions open longer than 10 minutes. Process id 25872 (only top 5 shown)
So it should be as easy as monitoring those two logfiles. But how it looks like on an ECP server, don't ask me.
You could try this way (I assume, your image is in *.jpg, *.png, *.gif, *.ico or *.bmp format and you use a Windows OS):
- save the stream to a temp file
- do $zf(-1,"pathToIrfanView.exe pathToInpFile /resize=(100,100) /aspectratio /convert=pathToOutFile")
- read the output into a stream and proceed as neededDon't forget, if one of the above path contains a space char, you have to put in quotes the whole path.
/resize=(100,100) /aspectration means, the picture will be resized to a max width/height of 100 by maintaning the aspect ratio. Example: input=2000x3000 out =67x100, input=3000x2000 out=100x67
For Unix exists similar tools to use with $zf(-1,...), for example "identify" to get the dimensions of the picture and "convert" or "imagemagick" for resizing.
As I wrote above, Java is not my case, sorry. Maybe the link below gives you some clue
https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=AFL_javagateway
I'm not that java guy, so just a hint only.
There should be a
public static java.lang.String PetNameLogicalToDisplay(...)method, so use/call this method to display your pets.