Eduard Lebedyuk · Jan 27, 2017 go to post

There should not be a problem with underscores:

set obj = ##class(%DynamicObject).%FromJSON("{""a_b"":1}")
w obj."a_b"
>1
Eduard Lebedyuk · Jan 25, 2017 go to post

Macros for method names which compile into AmethodName or methodName depending on global var set for compilation then.

 

Dynamic dispatch is a hit on speed anyway.

Eduard Lebedyuk · Jan 25, 2017 go to post

Always call

do a.AmethodName()

And inside dynamic dispatch check global variable %debug (or global, or some IsDebug method etc.). If it exists call both annotation methods and target method, If it does not exist only call target method.

Eduard Lebedyuk · Jan 25, 2017 go to post

Another approach would be using dynamic dispatch:

Let's say you have this method:

/// @NiceTest1
ClassMethod Test()
{
    Write 1
}

Using Class Generators you generate 2 additional methods:

/// @NiceTest1
ClassMethod OnBeforeTest()
{
    Write "Before NiceTest1"
}

/// @NiceTest1
ClassMethod OnAfterTest()
{
    Write "After NiceTest1"
}

and you add dynamic dispatch method (and dynamic dispatch classmethod) to the class:

/// Is used to implement an unknown method call.  It is also used
/// to resolve an unknown multidimensional property reference (to get the value
/// of a property) because that syntax is identical to a method call.
Method %DispatchMethod(Method As %String, Args...) [ ServerOnly = 1 ]
{
    // Amethod -> method
    set Method = $e(Method, 2, *)
    do $method(, "OnBefore" _ Method, Args...)
    do $method(, Method, Args...)
    do $method(,"OnAfter" _ Method,Args...)
}

So, as a whole it can look like this:

Class Utils.Annotations1 Extends %RegisteredObject
{

Method OnBeforeTest()
{
    Write "Init NiceTest1",!
}

/// @NiceTest1
Method Test()
{
    Write 1,!
}

Method OnAfterTest()
{
    Write "End NiceTest1",!
}

/// Is used to implement an unknown method call. 
Method %DispatchMethod(Method As %String, Args...) [ ServerOnly = 1 ]
{
    set Method = ..getMethodName(Method)
    do $method(, "OnBefore" _ Method, Args...)
    do $method(, Method, Args...)
    do $method(,"OnAfter" _ Method,Args...)
}

/// Is used to implement an unknown class method call
ClassMethod %DispatchClassMethod(Class As %String, Method As %String, Args...) [ ServerOnly = 1 ]
{
    set Method = ..getMethodName(Method)
    do $classmethod(, "OnBefore" _ Method, Args...)
    do $classmethod(, Method, Args...)
    do $classmethod(,"OnAfter" _ Method,Args...)
}

ClassMethod getMethodName(method As %String) As %String
{
    // Amethod -> method
    set method = $e(method, 2, *)
    return method
}

}

Works like this:

USER>do a.ATest()
Init NiceTest1
1
End NiceTest1
 
USER>do a.Test()
1
Eduard Lebedyuk · Jan 24, 2017 go to post

You can modify method code during compilation (obviously dangerous) using generators. Here's the sample that annotates all methods, containing @ in description:

Class Utils.Annotations
{

/// @NiceTest1
ClassMethod Test()
{
    Write 1
}

ClassMethod OnCompile() As %Status [ CodeMode = objectgenerator ]
{
    #dim sc As %Status = $$$OK
    for i=1:1:%class.Methods.Count() {
        #dim method As %Dictionary.MethodDefinition = %class.Methods.GetAt(i)
        if method.Description [ "@" {
            set sc = ..annotate(method)
            quit:$$$ISERR(sc)
        }
    }
    quit:$$$ISERR(sc) sc
    set sc = %class.%Save()
    quit sc
}

ClassMethod annotate(method As %Dictionary.MethodDefinition) As %Status
{
    #dim sc As %Status = $$$OK
    set code = method.Implementation.Read($$$MaxCacheInt)
    set code = ..cleadOldAnnotation(code)
    set code = ..addNewAnnotation(code, $e(method.Description, 2,*))
    
    do method.Implementation.Clear()
    do method.Implementation.Write(code)
    
    quit sc
}

ClassMethod cleadOldAnnotation(code As %String) As %String
{
    if $find(code, "//init annotation end") {
        set code = $e(code, $find(code, "//init annotation end") + 2, $find(code, "//complete annotation start") - $l("//complete annotation start") - 2)
    }
    return code
}

ClassMethod addNewAnnotation(code As %String, annotation As %String) As %String
{
    #define Tab $c(9)
    set code =  $$$Tab _ "Write ""Init " _ annotation _ """" _ $$$NL _
                $$$Tab _ "//init annotation end" _ $$$NL _
                code _
                $$$Tab _ "//complete annotation start"_ $$$NL _
                $$$Tab _ "Write ""End " _ annotation _ """"
    return code
}

}

Compiles into:

/// @NiceTest1
ClassMethod Test()
{
    Write "Init NiceTest1"
    //init annotation end
    Write 1
    //complete annotation start
    Write "End NiceTest1"
}

GitHub

Eduard Lebedyuk · Jan 20, 2017 go to post

Yes, you can query everything  you see in Message Viewer and Event Viewer. Their code is defined in EnsPortal.MessageViewer.zen and EnsPortal.EventLog.zen respectively. You can see the queries these pages use and adapt them, or inherit from them and publish it as another separate web application.

Also, here's modification example - Ensemble Log Viewer with namespace support.

Eduard Lebedyuk · Jan 19, 2017 go to post

You can specify Logfile setting for logging and these settings for debug:

  • JavaDebug: Allow a Java debugger (such as Eclipse or JSwat) to attach. If True, enables Java debugging via TCP. The default is False.
  • JavaDebugPort: Specify the port on which to listen. The default is 8000.
  • JavaDebugSuspend: If Yes, suspend the JVM on start to wait for the debugger to attach. The default is No.

Documentation.

Eduard Lebedyuk · Jan 17, 2017 go to post

%DB_CACHESYS may also be required, because data for this table is stored in CACHESYS database.

Eduard Lebedyuk · Jan 13, 2017 go to post

Thank you!

Do you import code from GitHub  repository into Ensemble instance automatically?

Eduard Lebedyuk · Jan 9, 2017 go to post

you are entirely correct. 

Good to hear.

$$$SIMSRCDOMENT

If I change algorithm to $$$SIMSRCDOMENT I don't receive any results (Results local is undefined).

If I choose $$$SIMSRCEQUIVS or $$$SIMSRCSIMPLE I  get Results local as expected.

What may be the reason? I didn't modify the domain between runs.

Method returns $$$OK and %objlasterror is empty using any algorithm.

Eduard Lebedyuk · Jan 9, 2017 go to post
write ##class(Config.CPF).Activate()

Would read and activate current configuration file without system restart.

Eduard Lebedyuk · Jan 9, 2017 go to post

You can search for the references in studio:

  1. Open Studio
  2. Menu -> Edit -> Search in files
    • Find: Dimension/Measure (for example [DateOfSale].[Actual].[DaySold])
    • File type: *.dfi

It should find relevant entities.

Eduard Lebedyuk · Jan 8, 2017 go to post

Hello.

Thank you for this information. I started testing it and %iKnow.Queries.SourceAPI:GetSimilar()  returned the following as a result local:

result(1)=$lb(890,":SQL:2002:20020308X00320",.4737,.9606,57,27,686,.4737)

The list is formed from these values:

$lb(srcId, externalId, percentageMatched, percentageNew, nbOfTgtsInRefSrc, nbOfTgtsInCommon, nbOfTgtsInSimSrc, matchScore)

What does that mean?

  • srcId -sourceId of similar document
  • externalId - external source id of similar document
  • percentageMatched - number of targets common between source and similar documents divided by number of targets in source document
  • percentageNew - number of targets in similar document that is not present in source document divided by total number of targets in similar document
  • nbOfTgtsInRefSrc - number of targets in source document
  • nbOfTgtsInCommon - number of targets common between source and similar documents
  • nbOfTgtsInSimSrc - number of targets in similar document
  • matchScore - seems equal to percentageMatched

Is that correct? Are there documentation on that?

Eduard Lebedyuk · Jan 5, 2017 go to post

Cache Fileserver is an old project of mine which allows file upload/download. Files have IDs, but to download each client get's an unique link active only for his IP for a limited time. You can remove IDs altogether.

Eduard Lebedyuk · Jan 5, 2017 go to post

If you have a web application, you can enforce codepage on a client side, there are several advantages to it:

  • Conversions do not add the load to the server
  • JS client libraries are well equipped to deal with various OSes/browsers combinations

The best approach would be to move to unicode.

Eduard Lebedyuk · Jan 2, 2017 go to post

You can define your own device of terminal type (also see System  - Configuration - Devices you can see other defined Cache terminals) :

Eduard Lebedyuk · Dec 28, 2016 go to post

Possible solution:

write $SYSTEM.Status.GetErrorText($SYSTEM.SQL.SetTCPKeepAlive(3600))

About TCPKeepAlive.

UPD: well, that did not work. I set it to 3600 and later to 30, and it did not help any.

Eduard Lebedyuk · Dec 28, 2016 go to post

The best way to add RESTForms (or any other repository) into your repository is submodules. Submodule is a pointer to specific commit from another repository. On disk it looks like folder. More info on submodules. To add RESTForms execute in git cli:

git submodule add https://github.com/intersystems-ru/RESTForms.git
Eduard Lebedyuk · Dec 26, 2016 go to post

Release page offers releases for both 2016.1 and 2016.2+. And in 2016.2+ $ methods are already removed.

If however you want to use latest commit from repo, then you need to run SMR.