Eduard Lebedyuk · Apr 22, 2018 go to post

Classes only.

Each method, that could be called from a terminal is documented with a sample call.

Eduard Lebedyuk · Apr 22, 2018 go to post

Try

chrome --headless --disable-gpu --print-to-pdf https://www.google.com/

Referenced article also shows several examples.

Chrome could be called with $zf(-1) function.

Eduard Lebedyuk · Apr 20, 2018 go to post

That looks like GZIP. Can you save response stream as a file and reopen it as a %Stream.FileCharacterGzip?

Eduard Lebedyuk · Apr 20, 2018 go to post

All properties names are written in:

Write $$$ZENJSONPROP(tPropName,pFormat)_": {"Write $$$ZENJSONPROP(tPropName,pFormat)_":["

To get current property XMLNAME parameter call this:

Write $$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME")
Eduard Lebedyuk · Apr 15, 2018 go to post

You can create computed property and index it.

Class A {

Property P1 As B;

Property P1P1 As %String [ SqlComputeCode = {set {*} = ##class(B).P1GetStored({P1})}, SqlComputed, SqlComputeOnChange = (%%INSERT, %%UPDATE) ];

Index I1 On P1P1;

}
Eduard Lebedyuk · Apr 14, 2018 go to post

Other locales could have TimeFormat property not equal to 1, there are also custom locales.

I completely agree that in a wide range of scenarios defaults work fine, or rather defaults are what we expect them to be. However, that is not always the case, so I prefer (and advice) to use macros for $zd* functions with all relevant parameters specified.

Eduard Lebedyuk · Apr 14, 2018 go to post

$zdt($H,3)

When working with $zd* functions It's better to specify what you need explicitly, because otherwise locale change can be an unwelcome surprise:

$zdt($H,3,1,0)
Eduard Lebedyuk · Apr 14, 2018 go to post

There are two operations:

  • comparing repository/instance
  • bringing one on compliance with other

The first part (comparison) could be easily generalized, as the underlying Git repository allows us to do it  regardless.

The second part, however is very specific and should be implemented as a part of the source control hooks. I don't see how it could be generalized.

In my GitLab code I specify an interface which end user should implement - it's a method that accepts a list of deleted items (filepaths). Implementations of this interface should first translate file paths into internal names (i.e. /src/Utils/Math.cls -> Utils.Math)  and then delete them.

That said, full build from scratch can solve the issue completely. That's a decent approach to take towards more "lively" environments.

Finally, as we're talking about deleting classes, at least for me it's an extremely rare case. Do you encounter it often? How & Why?

Eduard Lebedyuk · Apr 13, 2018 go to post

The only "automatic" solution I see here is to check out and import classes into clear or new Namespace.

  1. Build git diff.
  2. Import new/modified classes.
  3. Delete deleted classes.

Cache Tortoise Git automatically deletes classes deleted from repository.

Or never delete classes, only "deprecate" it

Depends on how much dead code you have. If say a few classes then it's fine. But large amounts of dead code just make codebase even harder to read.

Eduard Lebedyuk · Apr 13, 2018 go to post

Does my example compile for you?

Anyway, you should use #def1arg instead of #define as I suggested in the original answer.

Eduard Lebedyuk · Apr 13, 2018 go to post

How would you mark it as DEPRECATED?

As a comment on a first line.

Also, how would you handle MAC files?

The same.

3. Go through all of the files in Cache and check if it's in the physical OS folder, if not mark it DEPRECATED.

Well, if you decided to deprecate several classes then yes.

Check out this series of articles on Git and Continuous delivery:

First article covers git, branches and how it can all work together in development.

With Continuous Delivery you can easily automate the tasks of syncing your branches and environments.

Eduard Lebedyuk · Apr 13, 2018 go to post

You should delete it.

Let's say you have ClassA and ClassB. And ClassA calls methods of ClassB. Then you delete ClassB from the repository, but it stays locally. And everything is fine for you and works, but down the line you start a new installation and suddenly it does not work, because ClassB does not exist.

When you're working with Git, or any version control system for that matter, you can easily rollback to any state of the repository. So once you commited something you can always get it back.

On some of our projects we first mark stuff we want to delete as DEPRECATED. But it stays in the codebase and in the repository. After a while, after we're reasonably sure that we in fact do not need this, the actual delete from the repository and from the server happens.

Eduard Lebedyuk · Apr 11, 2018 go to post

 but I was unable to write to context.A08Msg.

How did you determine that?

Generally it's not a good idea to pass whole objects received from somewhere else, especially if they could be changed down the road. If we're talking about persistent objects then they have ids and all references to persistent objects are stored as ids in the database. At runtime the id is read and the object is loaded into memory as required.

Ensemble BPL process is a state machine that loads and unloads context to/from disk often, so if some other Ensemble host changes the object it would also change in the base BP after reload cycle and that can cause problems.

As a workaround you can assign clones, that is safe:

<assign property='context.A08Msg' value='request.%ConstructClone(1)'/>
Eduard Lebedyuk · Apr 11, 2018 go to post

My solution and how I got there.

I started with this:

r=1:1:s{c=1:1:s{r=1!(r=s)!(c=1)!(c=s)!(r=c)!(s=(c+r-1)){"#"}else{" "c=s{!}}}

First improvement was thanks to @Robert Cemper who suggested moving i c=s{w !}}} into a first for:

r=1:1:! c=1:1:r=1!(r=s)!(c=1)!(c=s)!(r=c)!(s=(c+r-1)){"#"}else{" "}

Finally got the idea of using $lb/$lf to get my best result of 76:

f r=1:1:s w ! f c=1:1:s w $s($lf($lb(c,r,r=s,c=s,c=r,r+c-s),1):"#",1:" ")

Some other ideas that didn't pan out.

First of all I thought about replacing $lf($lb)) with $f() but -1 and 1x numbers became a problem:

f r=1:1:s w ! f c=1:1:s w $s($f(c_r_(r=s)_(c=s)_(c=r)_$replace(r+c-s,-1,""),1):"#",1:" ")

Other idea was using $translate:

f r=1:1:s w ! f c=1:1:s w $tr(''$lf($lb(c,r,r=s,c=s,c=r,r+c-s),1),10,"# ")

Interestingly if we allow the box to be made of any symbols, some other solutions became possible. For example binary box (63 symbols):

f r=1:1:s w ! f c=1:1:s w '$lf($lb(c,r,r=s,c=s,c=r,r+c-s),1)
Eduard Lebedyuk · Apr 11, 2018 go to post

System users are logging fine via user/pass, but before that they try delegated and fail there so Audit gets a new record?

Eduard Lebedyuk · Apr 9, 2018 go to post

Let's finish this competition this Wednesday (so it would be a week) and publish our best efforts then.

Eduard Lebedyuk · Apr 9, 2018 go to post

Good idea too.

Apache PDFBox for PDF + Apache POI for Office files.

Or Apache TIKA can be used to extract text from everything (it's a wrapper around PDFBox and POI).

Eduard Lebedyuk · Apr 9, 2018 go to post

Right. Forgot about it.

You can use ghostscript, here's how. In your case command would probably look like this:

Parameter COMMAND = "%1 -dBATCH -dNOPAUSE -sDEVICE=txtwrite -sOutputFile=%2 %3";

ClassMethod pdf2txt(pdf, txt) As %Status
{
    set cmd = $$$FormatText(..#COMMAND, ..getGS(), txt, pdf)
    return ..execute(cmd)
}

/// Get gs binary
ClassMethod getGS()
{
    if $$$isWINDOWS {
        set gs = "gswin64c"
    } else {
        set gs = "gs"
    }
    return gs
}

Execute method code.

Also note, that PDF can contain only images instead of text. in that case you'd need OCR.