Eduard Lebedyuk · Dec 14, 2017 go to post

Try

set rowtype = "Code VARCHAR(2),Name VARCHAR(9)"
set filename = "c:\temp\Country.csv" 
do ##class(%SQL.Util.Procedures).CSVTOCLASS(2, .rowtype, filename,,,,"Test.CSV")

And check new Test.CSV class for import methods.

Eduard Lebedyuk · Dec 12, 2017 go to post

You have compilation error(s). That's why one or more methods are not generated, so instead methods in Ens.BusinessOperation gets called. These methods are returning not implemented error.

To start with 

 Extends (Ens.BusinessOperation, )

should be:

 Extends Ens.BusinessOperation

You can check which exact method has not been generated in Ensemble Event Log.

UPD. [@Rajiv Bhatia] solution is correct, my bad. Should have read your code.

Eduard Lebedyuk · Dec 12, 2017 go to post

 I feel the whole approach violates the statelessness of a REST architecture?

The request itself is stateless. For example session tracking is okay within REST despite the fact that session exists between requests. Here's how I understand violation of REST statelessness: let's say you have a newsfeed API /news and you return news in chunks of 20 elements. Users are authenticated.

REST way:

  • GET /news/1 - returns first 20 elements
  • GET /news/2 - returns elements 21-40
  • etc.

Not a REST way:

  • GET /news/next - returns first 20 elements
  • GET /news/next - returns elements 21-40
  • etc.

Now, the second approach violates REST principles because request itself - /news/next does not contain enough information to process it. Server should track how much pages each client received, and which page to return next.

To sum up: statelessness in REST means that request itself is enough to determine what do we need to do  with it and request does not require pulling any additional information about previous requests from the same client.

Eduard Lebedyuk · Dec 12, 2017 go to post

I did not test this approach, but something along these lines can help. The general idea is that SAX parser can validate against the XML schema, and we can use that.

1. Generate schema from your XML enabled classes.

2. Call %XML.Reader:Open method, and provide it with your xml data and schema:

#include %occSAX
set reader = ##class(%XML.Reader).%New()
set reader.SAXSchemaSpec = "/path/to/schema.xsd" // "maybe "file:///path/to/schema.xsd"
set reader.SAXFlags = $$$SAXFULLDEFAULT
set sc = reader.OpenString("<xml/>")
w $System.Status.GetErrorText(sc)


3. sc should contain errors, $$$SAXFULLDEFAULT is defined in %occSAX and contains several possible values:

#; ------------------------------------------------------------------------
#; Bit flags for %XML.SAX.Parser feature selection (flags argument)
#; ------------------------------------------------------------------------
 
#; Specify this value if you want to accept the SAX defaults (see below)
#;
#define SAXDEFAULTS 27
 
#; Specify this value if you want the SAX defaults plus namespaces prefixes/
#define SAXFULLDEFAULT 95
 
#;
#; Specify this bit if you want the parser to perform validation
 
#; http://xml.org/sax/features/validation 
#; On: Report all validation errors. (default) 
#; Off: Do not report validation errors. 
 
#define SAXVALIDATION 1
 
#;
#; Specify this bit if you want the parser to recognize namespaces
 
#; http://xml.org/sax/features/namespaces 
#; On: Perform Namespace processing (default) 
#; Off: Optionally do not perform Namespace processing 
 
#define SAXNAMESPACES 2
 
#;
#; Specify this bit if you want the parser to process namespace prefixes
 
#; http://xml.org/sax/features/namespace-prefixes 
#; On: Report the original prefixed names and attributes used for Namespace declarations 
#; Off: Do not report attributes used for Namespace declarations, and optionally do not report original prefixed names (default)
 
#define SAXNAMESPACEPREFIXES 4
 
#;
#; Specify this bit if you want the parser to perform validation dynamically
 
#; http://apache.org/xml/features/validation/dynamic 
#; On: The parser will validate the document only if a grammar is specified. (http://xml.org/sax/features/validation must be true) (default)
#; Off: Validation is determined by the state of the http://xml.org/sax/features/validation feature
 
#define SAXVALIDATIONDYNAMIC 8
 
#;
#; Specify this bit if you want the parser to recognize schemas
 
#; http://apache.org/xml/features/validation/schema 
#; On: Enable the parser's schema support. (default) 
#; Off: Disable the parser's schema support. 
#define SAXVALIDATIONSCHEMA 16
 
#; Specify this bit if you want the parser to perform full schema checking
 
#; http://apache.org/xml/features/validation/schema-full-checking
#; On: Enable full schema constraint checking, including checking which may be time-consuming or memory intensive. Currently, particle unique attribution constraint checking and particle derivation resriction checking are controlled by this option
#; Off: Disable full schema constraint checking (default). 
 
#define SAXVALIDATIONSCHEMAFULLCHECKING 32
 
#; http://apache.org/xml/features/validation/cache-grammarFromParse
#; On: Cache the grammar in the pool for re-use in subsequent parses
#; Off: Do not cache the grammar in the pool (default)
#; If set to true, the http://apache.org/xml/features/validation/use-cachedGrammarInParse is also set to true automatically.
#define SAXVALIDATIONREUSEGRAMMAR 64
 
#; Flags to force SAX not to validate but DO recognize namespaces and prefixes
#define SAXNOVALIDATION $$$SAXNAMESPACES+$$$SAXNAMESPACEPREFIXES

SAXFULLDEFAULT = All flags except SAXVALIDATIONSCHEMAFULLCHECKING.

Maybe try change the flags , but defaults seems to do what you need.

If you actually try this approach can you please post if it works or not?

Eduard Lebedyuk · Dec 10, 2017 go to post

Benjamin's link reads

https://sourceforge.net/projects/onforme/

but points to

https://sourceforge.net/projects/onforme/%C2%A0
Eduard Lebedyuk · Dec 9, 2017 go to post

1. cls is used by several others languages there, it's okay.

2. We need more than 100 CLS repositories to add our highlighting to GitHub

3. GitHub language grammar == Atom language grammar. We have one, but it needs work.

Eduard Lebedyuk · Dec 8, 2017 go to post

System Management Portal -> Menu -> Databases -> HSAUDIT -> Mount RO (remove check) -> Save.

Eduard Lebedyuk · Dec 8, 2017 go to post

Here's the code I ran:

Class User.XMLTest
{

/// do ##class(User.XMLTest).Test()
ClassMethod Test()
{
    set source = ..GetXData("Source")
    set xslt = ..GetXData("XSLT")
    #dim result As %Stream.Object
    set sc = ##class(%XML.XSLT.Transformer).TransformStream(source, xslt, .result)
    
    do result.OutputToDevice()
}

ClassMethod GetXData(name) As %Stream.TmpCharacter [ CodeMode = expression ]
{
##class(%Dictionary.XDataDefinition).IDKEYOpen($classname(), name).Data
}

XData Source
{
Your Message
}

XData XSLT
{
Your XSLT
}

}

and here's the result:

{
"Message" :
{
"Header" :
{
"Code" : "HOT",
"Date" : "2017-12-08 11:22:34.658"
}, "Body" : [
 
{
"Code" : "HOT",
"Name" : "SIDE",
"Type" : "AADULT",
"Sec" : "MSec",
"ardge" : "Adult",
"Nder" : "F",
"TBC" : "21",
"BO" : "14",
"DBOC" : "0",
"LBC" : "5",
"AB" : "2"
},

...

Check %objlasterror and also check your XML encoding, there may be problems if your encoding does not match declaration.

Eduard Lebedyuk · Dec 7, 2017 go to post

So, for now, yes. I changed to article

It was a question? My bad, I thought I created an article.

Eduard Lebedyuk · Dec 7, 2017 go to post

But how about getting not just a progress but how to get some data before task finished. 

Append to data global as required and get data on each check, not only for complete requests?

And also, I see beg security Issue, when I can get information from any other process. You use TaskId directly from the request like you trust everybody. And also easy to get SUBSCRIPT error.

I completely agree that it's unsecure and with no $get(). But it's a minimal implementation, so I skipped a lot of details.

BTW: do you suppose to acept someone's answer? Looks like it is mostly just discissing topic.

I think it's more of a discussion topic. That's why it's an article and not a question.

Eduard Lebedyuk · Dec 7, 2017 go to post

You're getting an error:

:ERROR{ERROR #5002: Cache error: <PROPERTY DOES NOT EXIST>zXMLTOJson+6^TestEnvironment.Custom.GENERAL.CUSTOM.XLT.XMLToJsonOperation1.1 *Parameters,EnsLib.EDI.XML}

Which means :

  • Class is EnsLib.EDI.XML
  • It does not have Parameters property
  • Error is found in the 6th line of zXMLTOJson routine in TestEnvironment.Custom.GENERAL.CUSTOM.XLT.XMLToJsonOperation1.1

6th line is probably this:

 Set tSC = ..Transform(tInput,tSSKey,pRequest.Parameters,.tOutput)

and pRequest object (of EnsLib.EDI.XML class) does not have Parameters property. Your call should probably be:

 Set tSC = ..Transform(tInput,tSSKey,pRequest,.tOutput)
Eduard Lebedyuk · Dec 7, 2017 go to post

I thought about actually building the tree in ppg and recursively iterating over it till the error is pinpointed. But it sure would take a lot of time to implement. What's your approach? Any shortcuts?

Eduard Lebedyuk · Dec 6, 2017 go to post

I first translated each word into normalized form - array of [letter, number of occurrences], ordered by letters. And then just checked if given normalized form already exists:

ClassMethod IsLettersUnique(word) As %Boolean
{
    set length = $length(word)
    for i=1:1:length {
        set letter = $e(word, i)
        set temp(letter) = $i(temp(letter))
    }
    
    set normalized = ""
    set key = ""
    for {
        set key=$order(temp(key),1, occurrences)
        quit:key=""
        set normalized = normalized _ key _ occurrences
    }
    
    quit:$d(%normalized(normalized))>0 $$$NO
    
    set %normalized(normalized) = 1
    
    quit $$$YES
}

Normalized words:

  • aaba -> a3b1
  • aaab -> a3b1
Eduard Lebedyuk · Dec 6, 2017 go to post

Add:

Set email.Charset = "UTF-8"
Set email.IsHTML = $$$YES

and add text in html, for example:

Do email.TextData.Write($$$FormatText("Hello %1!<br>Thank you for visiting %2!", "Name", "Location"))

Also if your BO has only one method you can name in OnMessage and remove XData altogether.

If new lines is really the only thing you need formatting-wise, you can use WriteLine method and send plain text emails:

Do email.TextData.WriteLine($$$FormatText("Thank you for your recent visit to %1.", "Location"))
Do email.TextData.WriteLine("We continue to look for ways to improve and your feedback is important.")
Do email.TextData.WriteLine($$$FormatText("Please take a few moments to complete our survey by following the link provided below, or by completing the paper survey you may have received at discharge from your recent visit at %1.", "Location"))
Eduard Lebedyuk · Dec 3, 2017 go to post

Should've done Day 3 part 1 same as you. Deriving the formula took me like half an hour.

Eduard Lebedyuk · Dec 2, 2017 go to post

I'm in. Here's my solution.

Thought about using $zstrip, but while it can remove duplicates, it can't leave only duplicates:

w $zstrip("11223","=E")
123

 

Also, for second task it says:

1212 produces 6: the list contains 4 items, and all four digits match the digit 2 items ahead.
1221 produces 0, because every comparison is between a 1 and a 2.

Shouldn't 1221 produce 3 as first 2 and second 1 match.

Currently failed on second task with 10938.

Eduard Lebedyuk · Dec 1, 2017 go to post

Would skip classes with  several levels of inheritance from %Persistent. Use SubclassOf query instead.

Eduard Lebedyuk · Dec 1, 2017 go to post

URL map can also be splitted into several parts:

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>

<!-- Api version 1 -->
<Map Prefix="/v1" Forward="Api.v1"/>

<!-- Api version 2 -->
<Map Prefix="/v2" Forward="Api.v2"/>

</Routes>
}

And brokers in Api.v1 and Api.v2 would process the requests according to their URL Map.

Eduard Lebedyuk · Nov 30, 2017 go to post

Complex functional indices which take a long time to build my be worth moving, otherwise - no.