Patrick Newton · Apr 27, 2020 go to post

Something to be aware of and which is perhaps not clear in our documentation ( I will check ) is that the metric values returned must be NUMERIC if you are going to use this API with our forthcoming SAM monitoring product. Values like 'OK 'and 'Normal ' and even '0d 1h 18maren't much use in rule evaluation and display in commonly available tools just as Grafana ( which we leverage in our solution).

Patrick Newton · Apr 23, 2020 go to post

gatekeeper has quarantined your httpd. open a terminal and navigate to {irisinstalldir}/httpd/bin and do this

sudo xattr -d com.apple.quarantine ./httpd. This removes the quarantine flag and will let httpd start.

alternative is to disable gatekeeper completely but I don't advise that as it can be dangerous.

Patrick Newton · Jun 12, 2019 go to post

Thats not a supported scenario at the moment. Feel free to log an enhancement request via the WRC.

Patrick Newton · Mar 14, 2019 go to post

You can't do that directly. SAX XML  parsing and XPATH are two completely different, unrelated, technologies. The best you could do would be to subclass the ContentHandler class and record the 'path'  as each element is reported. You would want to declare a transient property to hold the 'path' and then incrementally build it up as startElement() is called and pull it down when endElement() is called. When an error occurs, consult the value of the 'path' property. This won't give you an XPATH path but it will give you something similar to give you an idea of where you are in the document.

Patrick Newton · Dec 3, 2018 go to post
ROUTINE ColorJSON

#include %occStatus

    // demonstration of using %SyntaxColor to output coloring information in JSON format
    
    // example code to be syntax checked
    // - lines for the syntax checker must begin with space or tab if there is no label
    Set n=0
    Set code($I(n))=" Set sum=0"
    Set code($I(n))=" For i=1:1 {"
    Set code($I(n))="  Read ""Number (return to finish): "",in,!"
    Set code($I(n))="  If in="""" {Quit}"
    Set code($I(n))="  Set sum=sum+in"
    Set code($I(n))=" }"
    Set code($I(n))=" Write ""Sum is: "",sum,!"
    Set code($I(n))=" Quit"
    
    // list code to current device
    Write !,"Code:",!
    For lineno=1:1:n {
        Write lineno,": ",code(lineno),!
    }
    Write !,"--",!!
    
    // write code to a stream and rewind it for reading
    Set input=##class(%GlobalCharacterStream).%New() If '$IsObject(input) {$$$ThrowStatus(%objlasterror)}
    For lineno=1:1:n {
        $$$THROWONERROR(sc,input.WriteLine(code(lineno)))
    }
    $$$THROWONERROR(sc,input.Rewind())
        
    // stream for coloring-output
    Set output=##class(%GlobalCharacterStream).%New() If '$IsObject(output) {$$$ThrowStatus(%objlasterror)}
    
    // create syntax checker
    Set syn=##class(%SyntaxColor).%New() If '$IsObject(syn) {$$$ThrowStatus(%objlasterror)}
    
    // top-level language (moniker) of source code
    Set language="COS"
    
    // flags for JSON output ("K" can't be used with "C" or "H")
    Set flags="K"
    
    // invoke syntax checker
    // - the Color method returns 1 for OK, 0 for ERROR (same applies to the Languages and Attributes methods) 
    If 'syn.Color(input,output,language,flags,,,,.coloringerrors) {
        Throw ##class(%Exception.General).%New("- error calling %SyntaxColor:Color: "_syn.DLLResultCode) // error details are in the DLLResultCode property
    }

    If coloringerrors {
        Write "(coloring errors)",!!
    }
    
    Do ShowJSON(syn,output)
    
    Quit

    
ShowJSON(syn,stream)
{
    Write "Raw JSON:",!
    $$$THROWONERROR(sc,stream.Rewind())
    While 'stream.AtEnd {
        Write stream.ReadLine(,.sc),! If $$$ISERR(sc) {$$$ThrowStatus(sc)}
    }
    Write !,"--",!!

    Write "Decoded JSON:",!
    Write " - format is: OFFSET(COUNT) LANGUAGE:ATTRIBUTE",!
    $$$THROWONERROR(sc,stream.Rewind())
    Set json={}.%FromJSON(stream.Read(,.sc)) If $$$ISERR(sc) {$$$ThrowStatus(sc)}
    
    // for each line ..
    // (the %GetNext loops could alternatively be done using a For loop starting at 0) 
    Set linesiter=json.%GetIterator()
    While linesiter.%GetNext(.lineno,.linejson) {
    
        Write !,"Line ",lineno+1,! // this array is numbered from 0 so we need to add 1 to get a line number corresponding to the code listing
        
        // for each colored item in the line
        Set onelineiter=linejson.%GetIterator()
        While onelineiter.%GetNext(,.item) {
            Write " ",$$ShowItem(syn,item),!
        }        
    }
    Write !,"--",!!
}


ShowItem(syn,item)
{
    Quit item.p_"("_item.c_") "_$$Language(syn,item.l)_":"_$$Attribute(syn,item.l,item.s)
}


Language(syn,langindex)
{
    // in a real program this should be cached
    If 'syn.Languages(.languages) {Throw ##class(%Exception.General).%New("- error calling %SyntaxColor:Languages: "_syn.DLLResultCode)}
    Quit $List(languages,langindex+1) // first language index is 0 so we need to add 1 to langindex
}


Attribute(syn,langindex,attrindex)
{
    // in a real program this should be cached
    If 'syn.Attributes(langindex,.attributes) {Throw ##class(%Exception.General).%New("- error calling %SyntaxColor:Attributes: "_syn.DLLResultCode)}
    Quit $List(attributes,attrindex+1) // first attribute index is 0 so we need to add 1 to attrindex
}
Patrick Newton · Nov 22, 2017 go to post

Use the outline view, that properties window is a generic eclipse window and not related to class properties.

Patrick Newton · Oct 24, 2017 go to post

I think you misunderstand. You cannot just add an arbitrary name as a tag! the reference above of course is invalid because someTag does not appear in the dictionary. Each part of the property reference must appear in the dictionary for this to be valid so 'PatientPrimaryLanguageCodeSequence' and 'someTag' both must appear. For your reference :-

(0010,0101) VR=SQ VM=1 Patient's Primary Language Code Sequence

Patrick Newton · Oct 23, 2017 go to post

As regards point 3) T

The dictionary does contain the individual elements, for example in our work list demo we do this :-

Set tSC=pDocOut.SetValueAt("StationAET","DataSet.ScheduledProcedureStepSequence[1].ScheduledStationAETitle")If$$$ISERR(tSC) Quit

ScheduledStationAETitle appears in the dictionary with tag (0040,0001).

You will need to consult the NEMA DICOM online documentation to determine which sub-tags are valid for a particular structure, in the particular document you are sending. We (ISC) don't maintain that information ourselves.

Hope this helps

Patrick Newton · Oct 20, 2017 go to post

1) Use Job per connection. A DICOM service can handle multiple remote AETs including wildcard definitions.

2) That method takes a list of TRANSFER SYNTAXES not SOP classes. Use the UI to create a specific association definition.

3) You don't need to create the SQ explicitly , it will come into being when you set the first member, e.g. Something in the example below

Set tSC = pDocOut.SetValueAt("English", "DataSet.PatientPrimaryLanguageCodeSequence[1].Something")

Patrick Newton · May 23, 2017 go to post

No, you can't assume that. This is a significant feature that many customers will need. Sorry but I can't say more than that ;-)

Patrick Newton · May 23, 2017 go to post

Extending CORS support to CSP and not just REST is planned work but we do not have an ETA as yet

Patrick Newton · Apr 7, 2017 go to post

You need to choose 'install new software' then select Atelier from the Atelier update site. Just because you added the update site in the preferences it won't automatically download the plugin. You have to initiate that buy installing.

Hope this helps

Patrick Newton · Mar 23, 2017 go to post

I'm sorry it's policy to not comment about dates for availability of future releases.

Patrick Newton · Mar 22, 2017 go to post

As the implementor of the BPL engine I would caution against this approach.  There is an awful lot of book keeping you have to do to which is better handled by BPL. A technique which has worked well for me in the past is to create a context class which contains much of your logic and then reference that in a simple BPL which performs the calls asynchronously. This is done by setting the 'contextsuperclass' attribute on the BPL process element in the XDATA block. The BPL compiler will use th e named class as the superclass of the context class which it generates during the compilation phase.

Patrick Newton · Mar 22, 2017 go to post

This is known as 'edit strategy' and is not currently supported. It's on the product roadmap though as we do understand it's a very necessary feature. Thanks for your patience

Patrick Newton · Mar 12, 2017 go to post

Seems atelier is spelt incorrectly in the curl example, here's an example of use

curl --user jamien:SYS http://127.0.0.1:57772/api/atelier/


{"status":{"errors":[],"summary":""},"console":[],"result":{"content":{"version":"Cache for UNIX (Apple Mac OS X for x86-64) 2017.3 (Build 529U) Wed Feb 15 2017 01:28:51 EST","id":"DD2AAF5C-F6C1-11E6-AC71-38C986213273","api":2,"features":[{"name":"DEEPSEE","enabled":true},{"name":"ENSEMBLE","enabled":true},{"name":"HEALTHSHARE","enabled":false}],"namespaces":["%SYS","DOCBOOK","ENSDEMO","ENSEMBLE","SAMPLES","USER"]}}}

Patrick Newton · Mar 3, 2017 go to post

I think you are laboring under a misapprehension. You can only use the XSLT2 Cache functionality through the Java Gateway, originating your request from the cache server. It's s server-side technology. You can use XSLT extensions in Atelier ( or any other tool ) to test and debug your XSLT on filesystem files but you won't be able to use the server callback isc:evaluate() within those stylesheets.

Patrick Newton · Feb 9, 2017 go to post

You can have multiple projects in your workspace and thats the way to go.

Below is an overview of the synchronization strategy. You will see if that someone changes files on the server underneath you then conflicts will occur. With Atelier you need to focus on the fact that the source on the client is the 'source of truth' the server is where you run your code. Your workflow should be sourcecontrol -> client -> server.

Synchronization Services for the New Development Paradigm 

This document describes the current approach to client/server synchronization.

Documents may be edited on the client independently of a connection to a Caché server. However, when a connection is established with a server for the purposes of saving, compiling and running code, then the client and server must agree with respect to the version of documents that are being operated upon.

Each document that exists on a server has a hash value associated with it. Each time the document changes, the hash value also changes. The hash value represents the server's version of the document. It's important to keep in mind that there is only ever ONE current version of a document on a server. The hash value is an opaque value, as far as the user is concerned it's just a 'cookie'.

All that is necessary when a client pushes a document to the server, is for the client to specify (via the hash) the version of the document it is replacing on the server. If the current server hash and the hash passed to the server from the client are equal then there is a MATCH on version and the server can go ahead and SAVE the document. If the hashes don't MATCH then there is a CONFLICT and the document will NOT be saved on the server.

*

The key idea here is that you cannot successfully push a document from a client to a server unless you identify by version the server document you are replacing. The hashes allow you to do that.

*

In the case of creating a new file, the client will not know the server hash. In this case it just passes the empty string to the server as the server hash value.

If the server does not have that document (that is, it is new to the server too) then the hashes will MATCH, the operation will succeed and the server will return a new document hash.

If the server already has the document, then there is a CONFLICT, the operation will not succeed.

Conflicts have to be resolved before a document can be modified on the server. How the conflict is actually resolved really does not matter (one could pull the server version, merge the diffs or do whatever). What is important is that when the resolution on the client has been done, the client must update its cached server hash to reflect the current server version. This means that when the client passes that hash value back to the server on the next save, the versions will match and the modification will go ahead.

In the case of deleting a file, the client must once again specify the server hash (if it has it). A MATCH on the server will result in the document being deleted, a MISMATCH will result in a CONFLICT.

All this is predicated on the client's ability to cache the hashes according to client source file, server address, server namespace and server document. How the data is stored is not important, what is important is that the hashes must be cached and passed to the server when a document modification is requested.

It's also important that the hash cache is persisted in some sort of client database. If not, then the synchronization of sources would have to be redone each time an interaction with a server is initiated.

The relationship between client and server sources is shown in this diagram

PushPull.png

Patrick Newton · Feb 3, 2017 go to post

Server Sync does take some time. This is mitigated for intersystems distributed library databases by pre-populating meta data and placing it on the server.

See for example, {serverdir}/atelier/CACHELIB/Metadata.zip.

If you have libraries of code then you can generate your own metadata.zip and place it on the server under the appropriate directory. You can call %Atelier.v1.Utils.MetaData.Build(databasename) and then add the generated files to Metadata.zip. We don't do this for you because Caché doesn't have a portable means of creating zip files.

For occasions where you don't have this pre-populated metadata, the initial load can take some time. However following the initial sync, synchronization should be quick as we do sophisticated cacheing and reporting of server diffs. The delay can't be completely avoided because large amounts of meta data have to be transferred over the network.

Patrick Newton · Jan 24, 2017 go to post

Yes, Atelier requires all files to have a header which defines the metadata for the file. The extension of the file is not enough ( for example in an INT the language mode is important ). Normally you don't need to know the rules as Atelier will handle this for you.  For reference here are the rules. I'll ensure that they are added to the Atelier reference documentation

It is required that Caché sources be stored in the file system in a textual format as opposed to the XML format that we have been using for some time now. The primary purpose of this requirement is to facilitate easy comprehension, editing and the performance of diffs. 


The current XML format captures additional meta-data ( for example, 'language mode' ) that does not appear in the body of the document. Any textual format MUST be able to accommodate this meta-data to ensure that no information is lost. 
Therefore, for exporting .mac, .int, .inc, .bas, .mvb and .mvi items during export a single line of header information appears as the first line of text in the following format :-


Routine NAME [Type = TYPE, LanguageMode = MODE, Generated] "Routine" is a case insensitive string which identifies this document as being a routine document container NAME is the name of the routine item (case sensitive) Following the name there is an optional collection of keyword value pairs that are enclosed in square brackets '[' ']'.

Currently three keywords are supported :-

Type = TYPE. Where TYPE is one of bas, inc, int, mac, mvb, mvi.


LanguageMode = MODE. Where MODE is an integer that is supported as an argument to $SYSTEM.Process.LanguageMode(MODE).


Generated. Its presence indicates that the routine is generated.


The keywords are optional and if none is specified then the square brackets containing them should not be present (though it is NOT a syntax error to specify an empty pair of square brackets ([])).


The LanguageMode keyword applies only for Type=mac or Type=int and will be ignored for other types. The default value for the LanguageMode keyword is 0.


Whitespace is freely supported within the header

Everything that comes after the single first line is source content and MUST be formatted according to the established rules of the particular document type. There is no trailer that indicates the end of the document.

Patrick Newton · Jan 23, 2017 go to post

The first line of the routine has to be in a particular format. Check that you didn't break the formatting.

Patrick Newton · Jan 12, 2017 go to post

Thanks for your feedback. To some extent we are constrained by the eclipse framework with what we can do but clearly the things that you point out can be improved. We will be sure to take this into account in our continued development.