"
+ set tHighlight("ATTRIBUTE", $$$IKATTNEGATION) = ""
+
+ // append/override with explicit highlighting requirements
+ merge tHighlight = pHighlight
+
+ set tSentence = ##class(%iKnow.Queries.SentenceAPI).GetHighlighted(pDomainId, pSentenceId, .tHighlight,,, .pSC)
+
+ } catch (ex) {
+ set pSC = ex.AsStatus()
+ }
+ quit tSentence
+}
+
+/// Retrieves the top entities similar to pString and prints them to JSON
+ClassMethod GetEntities(pDomainId As %Integer) As %Status
+{
+ set tSC = $$$OK
+ try {
+ if $isobject(%request.Content.blacklists) {
+ set tBlacklists = ""
+ for i = 1:1:%request.Content.blacklists.Count() {
+ set tBlacklists = tBlacklists_$lb(%request.Content.blacklists.GetAt(i))
+ }
+ } else {
+ set tBlacklists = ""
+ }
+
+ if (%request.Content.entity = "") {
+ set tSC = ##class(%iKnow.Queries.EntityAPI).GetTop(.tResult, pDomainId, 1, ..#IKPAGESIZE, ..GetFilter(pDomainId), ..#IKPFILTERMODE,,,, tBlacklists)
+ quit:$$$ISERR(tSC)
+ } else {
+ set tSC = ##class(%iKnow.Queries.EntityAPI).GetSimilar(.tResult, pDomainId, %request.Content.entity, 1, ..#IKPAGESIZE, ..GetFilter(pDomainId), ..#IKPFILTERMODE,, tBlacklists)
+ quit:$$$ISERR(tSC)
+ }
+
+ set:$data(%response) %response.ContentType="application/json"
+ set tJSON = ##class(%ZEN.proxyObject).%New()
+ set tJSON.Seed = %request.Content.entity
+
+ set tSC = ..EntityResultToJSON(.tResult, .tEntities)
+ quit:$$$ISERR(tSC)
+
+ set tJSON.Entities = tEntities
+ do tJSON.%ToJSON(,..#JSONFORMATPARAMS)
+
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+/// Utility method for converting an array of entities to JSON
+ClassMethod EntityResultToJSON(ByRef pResult, Output pJSONArray) As %Status [ Private ]
+{
+ set tSC = $$$OK
+ try {
+ set i = "", pJSONArray = ##class(%ListOfObjects).%New()
+ for {
+ set i = $order(pResult(i), 1, tData)
+ quit:i=""
+
+ set tProxy = ##class(%ZEN.proxyObject).%New()
+ set tProxy.EntityValue = $lg(tData,2)
+ set tProxy.Frequency = $lg(tData,3)
+ set tProxy.Spread = $lg(tData,4)
+ do pJSONArray.Insert(tProxy)
+ }
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit tSC
+}
+
+ClassMethod GetCRCs(pDomainId As %Integer) As %Status
+{
+ set tSC = $$$OK
+ try {
+ set tSC = ##class(%iKnow.Queries.CrcAPI).GetByEntities(.tResult, pDomainId, %request.Content.entity, 1, ..#IKPAGESIZE, ..GetFilter(pDomainId), ..#IKPFILTERMODE)
+ quit:$$$ISERR(tSC)
+
+ set:$data(%response) %response.ContentType="application/json"
+ set tJSON = ##class(%ZEN.proxyObject).%New()
+ set tJSON.Seed = %request.Content.entity
+
+ set tSC = ..CRCResultToJSON(.tResult, .tCRCs)
+ quit:$$$ISERR(tSC)
+
+ set tJSON.CRCs = tCRCs
+ do tJSON.%ToJSON(,..#JSONFORMATPARAMS)
+
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+/// Utility method for converting an array of entities to JSON
+ClassMethod CRCResultToJSON(ByRef pResult, Output pJSONArray) As %Status [ Private ]
+{
+ set tSC = $$$OK
+ try {
+ set i = "", pJSONArray = ##class(%ListOfObjects).%New()
+ for {
+ set i = $order(pResult(i), 1, tData)
+ quit:i=""
+
+ set tProxy = ##class(%ZEN.proxyObject).%New()
+ set tProxy.Value = $lts($li(tData,2,4)," ~ ")
+ set tProxy.Frequency = $lg(tData,5)
+ set tProxy.Spread = $lg(tData,6)
+ do pJSONArray.Insert(tProxy)
+ }
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit tSC
+}
+
+/// Retrieves information about all sets stored for domain pDomain
+/// Writes the following JSON output:
+/// {
+/// Sets: [
+/// {
+/// SetId: 123,
+/// Name: 'abc',
+/// Entities: [ 'xyz', 'def', ... ]
+/// },... ],
+/// TotalInSets: x,
+/// TotalNotInSets: x,
+/// TotalSources: x
+/// }
+ClassMethod GetSetInfo(pDomainId As %Integer) As %Status
+{
+ set tSC = $$$OK
+ try {
+ set:$data(%response) %response.ContentType="application/json"
+ set tJSON = ##class(%ZEN.proxyObject).%New()
+
+ set tSQL = "SELECT ID FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = "_pDomainId
+ set tResult = ##class(%SQL.Statement).%ExecDirect(,tSQL)
+ set tJSON.Sets = ##class(%ListOfObjects).%New()
+ while tResult.%Next() {
+ set tSetDef = ##class(SetDefinition).%OpenId(tResult.%Get("ID"))
+ set tProxy = ##class(%ZEN.proxyObject).%New()
+ set tProxy.SetId = tResult.%Get("ID")
+ set tProxy.Name = tSetDef.Name
+ set tProxy.Entities = tSetDef.Entities
+ set tProxy.CRCs = tSetDef.CRCs
+ set tProxy.Logic = tSetDef.Logic
+ set tProxy.Sources = $s($isobject(tSetDef.GetFilter()):tSetDef.GetFilter().FilteredSourceCount, 1:0)
+ do tJSON.Sets.Insert(tProxy)
+ }
+
+ // now get the counts
+ set tJSON.TotalSources = ##class(%iKnow.Queries.SourceAPI).GetCountByDomain(pDomainId)
+ set tJSON.TotalNotInSets = ..GetNotInSetFilter(pDomainId, .tSC).FilteredSourceCount
+ quit:$$$ISERR(tSC)
+ set tJSON.TotalInSets = tJSON.TotalSources - tJSON.TotalNotInSets
+
+ // write JSON
+ do tJSON.%ToJSON(,..#JSONFORMATPARAMS)
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+/// Saves the posted set information to a SetDefintion, appending the supplied list of
+/// entities to any that might already exist for the set specified in the request.
+/// Accepts the following JSON (as HTTP POST content):
+/// {
+/// SetId: 123,
+/// Name: 'name',
+/// Entities: [ 'ent1', 'ent2' ],
+/// Logic: 'abc AND def'
+/// }
+ClassMethod SaveSet(pDomainId As %Integer) As %Status
+{
+ set tSC = $$$OK
+ try {
+ // retrieve or instantiate set
+ set:%request.Content.SetId tSetDef = ##class(SetDefinition).%OpenId(%request.Content.SetId)
+ set:$g(tSetDef)="" tSetDef = ##class(SetDefinition).NameIdxOpen(pDomainId, %request.Content.Name)
+ if tSetDef="" {
+ set tSetDef = ##class(SetDefinition).%New()
+ set tSetDef.Name = %request.Content.Name
+ set tSetDef.DomainId = pDomainId
+ }
+
+ // check which entities are already in there and append
+ for i = 1:1:tSetDef.Entities.Count() {
+ set tEntity = tSetDef.Entities.GetAt(i)
+ set tCurrentEntities(tEntity)=""
+ }
+ if $isobject(%request.Content.Entities) {
+ for i = 1:1:%request.Content.Entities.Count() {
+ set tEntity = %request.Content.Entities.GetAt(i)
+ do:'$d(tCurrentEntities(tEntity)) tSetDef.Entities.Insert(tEntity)
+ }
+ }
+
+ // same for CRCs
+ for i = 1:1:tSetDef.CRCs.Count() {
+ set tCRC = tSetDef.CRCs.GetAt(i)
+ set tCurrentCRCs(tCRC)=""
+ }
+ if $isobject(%request.Content.CRCs) {
+ for i = 1:1:%request.Content.CRCs.Count() {
+ set tCRC = %request.Content.CRCs.GetAt(i)
+ do:'$d(tCurrentCRCs(tCRC)) tSetDef.CRCs.Insert(tCRC)
+ }
+ }
+
+ // update logic
+ set tSetDef.Logic = %request.Content.Logic
+
+ set tSC = tSetDef.%Save()
+ quit:$$$ISERR(tSC)
+
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+/// Removes a single entity from a set.
+/// Accepts the following JSON (as HTTP POST content):
+/// {
+/// SetId: 123,
+/// Name: 'name',
+/// RemoveEntity: 'ent1'
+/// }
+ClassMethod UpdateSet(pDomainId As %Integer) As %Status
+{
+ set tSC = $$$OK
+ try {
+ // retrieve set
+ set:%request.Content.SetId tSetDef = ##class(SetDefinition).%OpenId(%request.Content.SetId)
+ set:$g(tSetDef)="" tSetDef = ##class(SetDefinition).NameIdxOpen(pDomainId, %request.Content.Name)
+ quit:tSetDef=""
+ if (%request.Content.Type="entity") {
+ for i = 1:1:tSetDef.Entities.Count() {
+ if (%request.Content.Value=tSetDef.Entities.GetAt(i)) {
+ do tSetDef.Entities.RemoveAt(i)
+ quit
+ }
+ }
+ } else {
+ for i = 1:1:tSetDef.CRCs.Count() {
+ if (%request.Content.Value=tSetDef.CRCs.GetAt(i)) {
+ do tSetDef.CRCs.RemoveAt(i)
+ quit
+ }
+ }
+ }
+
+ set tSC = tSetDef.%Save()
+ quit:$$$ISERR(tSC)
+
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+/// Deletes a SetDefinition instance from the table.
+/// Accepts the following JSON (as HTTP POST content):
+/// {
+/// SetId: 123
+/// }
+ClassMethod DeleteSet(pDomainId As %Integer) As %Status
+{
+ set tSC = $$$OK
+ try {
+ set tSC = ##class(SetDefinition).%DeleteId(%request.Content.SetId)
+ quit:$$$ISERR(tSC)
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+/// Retrieves the overlap information for SetDefintion pSetId, listing
+/// how many sources it has in common with all other sets.
+/// Writes the following JSON:
+/// {
+/// SetId: 123,
+/// Name: 'abc',
+/// Overlaps: [
+/// {
+/// SetId: 456,
+/// Name: 'def',
+/// Count: 789
+/// },... ]
+/// }
+ClassMethod GetSetOverlap(pDomainId As %Integer, pSetId As %Integer) As %Status
+{
+ set tSC = $$$OK
+ try {
+ set:$data(%response) %response.ContentType="application/json"
+
+ set tSetDef = ##class(SetDefinition).%OpenId(pSetId)
+ set tJSON = ##class(%ZEN.proxyObject).%New()
+ set tJSON.SetId = pSetId
+ set tJSON.Name = tSetDef.Name
+
+ set tSQL = "SELECT ID FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = "_pDomainId //_" AND ID != "_pSetId
+ set tResult = ##class(%SQL.Statement).%ExecDirect(,tSQL)
+ set tJSON.Overlaps = ##class(%ListOfObjects).%New()
+ while tResult.%Next() {
+ set tOtherSetDef = ##class(SetDefinition).%OpenId(tResult.%Get("ID"))
+ set tProxy = ##class(%ZEN.proxyObject).%New()
+ set tProxy.SetId = tResult.%Get("ID")
+ set tProxy.Name = tOtherSetDef.Name
+
+ set tFilter = ##class(%iKnow.Filters.GroupFilter).%New(pDomainId,$$$GROUPFILTERAND)
+ do tFilter.AddSubFilter(tSetDef.GetFilter())
+ do tFilter.AddSubFilter(tOtherSetDef.GetFilter())
+ set tProxy.Count = tFilter.FilteredSourceCount
+
+ do tJSON.Overlaps.Insert(tProxy)
+ }
+
+ // write JSON
+ do tJSON.%ToJSON(, ..#JSONFORMATPARAMS)
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+/// Utility method to retrieve a %iKnow.Filters.Filter object representing all sources
+/// not part of any set.
+ClassMethod GetNotInSetFilter(pDomainId As %Integer, Output pSC As %Status) As %iKnow.Filters.Filter [ Internal ]
+{
+ set pSC = $$$OK, tFilter=""
+ try {
+ set tAllEntities=""
+ set tResult = ##class(%SQL.Statement).%ExecDirect(,"SELECT $listtostring(Entities) FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = "_pDomainId)
+ while tResult.%Next() {
+ set tEntities = tResult.%GetData(1), tCount = $l(tEntities,",")
+ for i = 1:1:tCount {
+ set tEntity = $p(tEntities,",",i)
+ continue:tEntity=""
+ set tAllEntities = tAllEntities _ $lb(tEntity)
+ }
+ }
+ if '$d(tAllEntities) {
+ set tFilter = ##class(%iKnow.Filters.SourceIdFilter).%New(pDomainId, 0)
+ } else {
+ set tFilter = ##class(%iKnow.Filters.GroupFilter).%New(pDomainId,$$$GROUPFILTERAND,1) // =NOT
+ do tFilter.AddSubFilter(##class(%iKnow.Filters.ContainsEntityFilter).%New(pDomainId, .tAllEntities))
+ }
+ } catch (ex) {
+ set pSC = ex.AsStatus()
+ }
+ quit tFilter
+}
+
+/// Simple error handler, converting a %Status object to a JSON representation.
+ClassMethod ErrorHandler(Stat As %Status) As %Status [ Private ]
+{
+ if $$$ISERR(Stat) {
+ set errorcode=$piece(##class(%SYSTEM.Status).GetErrorCodes(Stat),",")
+ set errormessage=##class(%SYSTEM.Status).GetOneStatusText(Stat)
+ set errobj=##class(%ZEN.proxyObject).%New()
+ set errobj.ErrorNum=errorcode
+ set errobj.ErrorMessage=errormessage
+ Set %response.ContentType="application/json"
+ Do ##class(%ZEN.Auxiliary.jsonProvider).%ObjectToJSON(errobj)
+ set errobj=""
+ }
+ quit $$$OK
+}
+
+ClassMethod GetSentimental(pDomainId As %Integer) As %Status
+{
+ set tSC = $$$OK
+ try {
+ if $isobject(%request.Content.blacklists) {
+ set tBlacklists = ""
+ for i = 1:1:%request.Content.blacklists.Count() {
+ set tBlacklists = tBlacklists_$lb(%request.Content.blacklists.GetAt(i))
+ }
+ } else {
+ set tBlacklists = ""
+ }
+
+ set:$data(%response) %response.ContentType="application/json"
+
+ set tJSON = ##class(%ZEN.proxyObject).%New()
+
+ set tDomain = ##class(%iKnow.Domain).%OpenId(pDomainId)
+ if '$isobject(tDomain) { set tSC = $$$ERROR($$$IKNoDomainWithId, pDomainId) }
+ set tPackageName = tDomain.GetParameter($$$IKPPACKAGE)
+ if (tPackageName="") { write "{ ""Entities"": [] }" quit }
+ set tPartTable = $tr(tPackageName,".","_")_".Part"
+
+ set tSQL = "SELECT * FROM "_
+ "(SELECT Entity->EntUniId EntUniId, Entity->EntityValue EntityValue, SUM(Positive) TotalPositive, SUM(Negative) TotalNegative, Entity->CorpusFrequency TotalFrequency FROM "_
+ "((SELECT Entity, 1 Positive, 0 Negative FROM "_tPartTable_" WHERE FOR SOME %ELEMENT(Attributes) ((%KEY = 'ATP:5') OR (%KEY = 'ATS:5')) AND EntTypeId = 0) "_
+ "UNION ALL "_
+ "(SELECT Entity, 0 Positive, 1 Negative FROM "_tPartTable_" WHERE FOR SOME %ELEMENT(Attributes) ((%KEY = 'ATP:6') OR (%KEY = 'ATS:6')) AND EntTypeId = 0)) u "_
+ "GROUP BY Entity) "_
+ "ORDER BY (TotalPositive+TotalNegative) DESC"
+
+ set tResult = ##class(%SQL.Statement).%ExecDirect(,tSQL)
+ set tJSON.Entities = ##class(%ListOfObjects).%New()
+ while tResult.%Next() {
+
+ if (tBlacklists'="") {
+ set tIsBlacklisted = 0, ptr=0, tEntUniId = tResult.%Get("EntUniId")
+ while $listnext(tBlacklists,ptr,tBlacklistID) {
+ set tIsBlacklisted = ##class(%iKnow.Utils.MaintenanceAPI).BlacklistContainsElement(pDomainId,tBlacklistID,tEntUniId)
+ quit:tIsBlacklisted
+ }
+ continue:tIsBlacklisted
+ }
+
+ set tEntity = ##class(%ZEN.proxyObject).%New()
+ set tEntity.EntityValue = tResult.%Get("EntityValue")
+ set tEntity.TotalPositive = tResult.%Get("TotalPositive")
+ set tEntity.TotalNegative = tResult.%Get("TotalNegative")
+ set tEntity.TotalFrequency = tResult.%Get("TotalFrequency")
+ do tJSON.Entities.Insert(tEntity)
+ }
+
+ // write JSON
+ do tJSON.%ToJSON(, ..#JSONFORMATPARAMS)
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+ClassMethod GetFeatures(pDomainId As %Integer) As %Status
+{
+ set tSC = $$$OK
+ try {
+ set:$data(%response) %response.ContentType="application/json"
+
+ set tJSON = ##class(%ZEN.proxyObject).%New()
+
+ set tDomain = ##class(%iKnow.Domain).%OpenId(pDomainId)
+ if '$isobject(tDomain) { set tSC = $$$ERROR($$$IKNoDomainWithId, pDomainId) }
+ set tPackageName = tDomain.GetParameter($$$IKPPACKAGE)
+ set tJSON.HasTables = (tPackageName'="")
+
+ if tJSON.HasTables {
+ set tSQL = "SELECT TOP 1 %ID FROM "_$tr(tPackageName,".","_")_".PathAttribute WHERE AttributeTypeId IN (5,6) UNION SELECT TOP 1 %ID FROM "_$tr(tPackageName,".","_")_".SentenceAttribute WHERE AttributeTypeId IN (5,6)"
+ set tResult = ##class(%SQL.Statement).%ExecDirect(,tSQL)
+ set tJSON.HasSentiment = (tResult.%Next() && tResult.%GetData(1))
+ } else {
+ set tJSON.HasSentiment = 0
+ }
+
+ set tJSON.MinSearchLength = tDomain.GetParameter($$$IKPMINTOPCONCEPTLENGTH)
+
+ kill tResult
+ set tJSON.Blacklists = ##class(%ListOfObjects).%New()
+ set tSC = ##class(%iKnow.Utils.MaintenanceAPI).GetBlackLists(.tResult, pDomainId, 1)
+ quit:$$$ISERR(tSC)
+ set i = ""
+ for {
+ set i = $order(tResult(i),1,tData)
+ quit:i=""
+ set tProxy = ##class(%ZEN.proxyObject).%New()
+ set tProxy.ID = $lg(tData,1)
+ set tProxy.Name = $lg(tData,2)
+ do tJSON.Blacklists.Insert(tProxy)
+ }
+
+ // write JSON
+ do tJSON.%ToJSON(, ..#JSONFORMATPARAMS)
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+ClassMethod OnPreDispatch(pUrl As %String, pMethod As %String, ByRef pContinue As %Boolean) As %Status
+{
+ set tSC = $$$OK
+ try {
+ // read request object
+ if (pMethod'="POST") || (%request.Content="") {
+ set %request.Content = ##class(%ZEN.proxyObject).%New()
+ } elseif '$isobject(%request.Content) {
+ set tSC = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(%request.Content,,.tRequestObject)
+ quit:$$$ISERR(tSC)
+ set %request.Content = tRequestObject
+ } elseif %request.Content.AtEnd {
+ set %request.Content = ##class(%ZEN.proxyObject).%New()
+ } else {
+ set tJSONString = ""
+ while '%request.Content.AtEnd {
+ set tJSONString = tJSONString_$zcvt(%request.Content.ReadLine(),"I","UTF8")
+ }
+ set tSC = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(tJSONString,,.tRequestObject)
+ quit:$$$ISERR(tSC)
+ set %request.Content = tRequestObject
+ }
+
+ } catch ex {
+ set tSC = ex.AsStatus()
+ }
+ quit ..ErrorHandler(tSC)
+}
+
+}
+
diff --git a/src/cls/Demo/SetAnalysis/SetDefinition.cls b/src/cls/Demo/SetAnalysis/SetDefinition.cls
index 13626fc..0d763f1 100644
--- a/src/cls/Demo/SetAnalysis/SetDefinition.cls
+++ b/src/cls/Demo/SetAnalysis/SetDefinition.cls
@@ -1,272 +1,273 @@
-/// This class represents sets saved from the SetAnalysis demo application.
-Class Demo.SetAnalysis.SetDefinition Extends %Persistent
-{
-
-Property DomainId As %Integer;
-
-Property Name As %String;
-
-Property Entities As list Of %String(MAXLEN = "");
-
-Property CRCs As list Of %String(MAXLEN = "");
-
-Property Logic As %String(MAXLEN = 2000);
-
-Property Type As %String [ Calculated, ReadOnly, SqlComputeCode = { set {*} = $s({Logic}'="":"composite", 1:"entities")}, SqlComputed ];
-
-Index NameIdx On (DomainId, Name) [ Unique ];
-
-Index EntitiesIdx On (DomainId, Entities(ELEMENTS)) [ Type = bitmap ];
-
-Index CRCsIdx On (DomainId, CRCs(ELEMENTS)) [ Type = bitmap ];
-
-Method GetSDFilter() As SetDefinitionFilter
-{
- quit ##class(SetDefinitionFilter).%New(..DomainId,..Name)
-}
-
-/// Retrieves a %iKnow.Filters.Filter instance representing all the sources
-/// in this set.
-Method GetFilter() As %iKnow.Filters.Filter
-{
- if (..Logic="") {
- set tEntities = ""
- for i = 1:1:..Entities.Count() {
- set tEntities = tEntities _ $lb(..Entities.GetAt(i))
- }
- if tEntities="" {
- set tEntityFilter = ""
- } else {
- set tEntityFilter = ##class(%iKnow.Filters.ContainsEntityFilter).%New(..DomainId, .tEntities)
- }
- if '..CRCs.Count() {
- quit tEntityFilter
- }
-
- // if we still have to filter by CRCs, create a SourceIdFilter
- set tAllCRCs = ""
- for i = 1:1:..CRCs.Count() {
- set tValue = $lfs(..CRCs.GetAt(i)," ~ ")
- set tAllCRCs = tAllCRCs_$lb(tValue)
- }
- do ##class(%iKnow.Queries.SourceAPI).GetByCrcs(.tResult, ..DomainId, tAllCRCs, 0, 0)
- set i = ""
- for {
- set i = $o(tResult(i),1,tData)
- quit:i=""
- set tAllSources(+$lg(tData,1))=""
- }
- set tCRCFilter = ##class(%iKnow.Filters.SourceIdFilter).%New(..DomainId, .tAllSources)
- if (tEntityFilter="") {
- quit tCRCFilter
- } else {
- set tFilter = ##class(%iKnow.Filters.GroupFilter).%New(..DomainId, "OR")
- do tFilter.AddSubFilter(tEntityFilter)
- do tFilter.AddSubFilter(tCRCFilter)
- quit tFilter
- }
-
- } else {
-
- set tSC = ..ParseLogic(..DomainId, ..Logic, .tTree)
- if $$$ISERR(tSC) { $$$ThrowStatus(tSC) }
- for tNode = tTree:-1:0 {
- set tOperator = $g(tTree(tNode,"operator"),"AND")
- set tNegated = $g(tTree(tNode,"negated"), 0)
- set tFilters(tNode) = ##class(%iKnow.Filters.GroupFilter).%New(..DomainId, tOperator, tNegated)
- set tChild = ""
- for {
- set tChild = $o(tTree(tNode,"children",tChild))
- quit:tChild=""
- do tFilters(tNode).AddSubFilter(tFilters(tChild))
- }
- for tLeaf = 1:1:$g(tTree(tNode,"leaf")) {
- if $d(tTree(tNode,"leaf",tLeaf,"negated")) {
- set tLeafFilter = ##class(%iKnow.Filters.GroupFilter).%New(..DomainId, "AND", 1)
- do tLeafFilter.AddSubFilter(..NameIdxOpen(..DomainId, tTree(tNode,"leaf",tLeaf)).GetFilter())
- } else {
- set tLeafFilter = ..NameIdxOpen(..DomainId, tTree(tNode,"leaf",tLeaf)).GetFilter()
- }
- do tFilters(tNode).AddSubFilter(tLeafFilter)
- }
- }
- quit tFilters(0)
- }
-}
-
-ClassMethod NameIsValid(pName As %String) As %Status
-{
- quit:$zstrip(pName,"<>W")'=pName $$$ERROR($$$GeneralError,"Set name cannot have leading or trailing whitespace")
- quit:$f(pName,"(")+$f(pName,")") $$$ERROR($$$GeneralError,"Set name cannot have parentheses")
- quit:$zstrip(pName,"*C")'=pName $$$ERROR($$$GeneralError,"Set name cannot contain control characters")
- quit:$find(" "_$$$UPPER(pName)_" "," AND ") $$$ERROR($$$GeneralError,"Set name cannot contain reserved word AND")
- quit:$find(" "_$$$UPPER(pName)_" "," OR ") $$$ERROR($$$GeneralError,"Set name cannot contain reserved word OR")
- quit:$find(" "_$$$UPPER(pName)_" "," NOT ") $$$ERROR($$$GeneralError,"Set name cannot contain reserved word NOT")
- quit $$$OK
-}
-
-Method %OnValidateObject() As %Status [ Private, ServerOnly = 1 ]
-{
- quit:(..Logic'="")&&..Entities.Count() $$$ERROR($$$GeneralError,"A set cannot be both based on entities and other sets")
- quit ..ParseLogic(..DomainId, ..Logic)
-}
-
-ClassMethod ParseLogic(pDomainId As %Integer, pLogic As %String, Output pTree) As %Status [ Private ]
-{
- kill pTree
- set tSC = $$$OK, pTree=0
- try {
- set pLogic = $replace($replace(pLogic,")"," ) "),"("," ( ")
- set pLogic = $zstrip($zstrip(pLogic,"=W"),"*C")
- set tAnnotated = $translate($$$UPPER(pLogic),"()",$c(0,1))
- set tAnnotated = $replace(tAnnotated," AND "," "_$c(2,2,2)_" ")
- set tAnnotated = $replace(tAnnotated," OR "," "_$c(3,3)_" ")
- set tAnnotated = $replace(tAnnotated," NOT "," "_$c(4,4,4)_" ")
-
- set tPos=0, tEndPos = $l(pLogic), tCurrent="", tNode=0, tNegateNext=0
- while $i(tPos)<=tEndPos {
- set tChar = $e(tAnnotated,tPos), tCharCode=$a(tChar)
-
- // opening parentheses: start new node
- if (tCharCode=0) {
- do AddLeaf
- set pTree($i(pTree),"parent")=tNode
- set pTree(tNode,"children",pTree)=""
- set tNode = pTree
- set:tNegateNext pTree(tNode,"negated")=1, tNegateNext=0
- continue
- }
-
- // close parentheses: end current node and go back up
- elseif (tCharCode=1) {
- do AddLeaf
- set:'$d(pTree(tNode,"operator")) pTree(tNode,"operator") = "AND"
- set tNode = $g(pTree(tNode,"parent"),-1)
- if (tNode<0) {
- set tSC = $$$ERROR($$$GeneralError, "Illegal combination of sets, check parentheses")
- quit
- }
- continue
- }
-
- // operator: AND
- elseif (tCharCode=2) {
- do AddLeaf
- if $d(pTree(tNode,"operator"),tPrevOperator) && (tPrevOperator'="AND") {
- set tSC = $$$ERROR($$$GeneralError, "Cannot mix operators")
- quit
- }
- set pTree(tNode,"operator") = "AND"
- set tPos=tPos+3
- }
-
- // operator: OR
- elseif (tCharCode=3) {
- do AddLeaf
- if $d(pTree(tNode,"operator"),tPrevOperator) && (tPrevOperator'="OR") {
- set tSC = $$$ERROR($$$GeneralError, "Cannot mix operators")
- quit
- }
- set pTree(tNode,"operator") = "OR"
- set tPos=tPos+2
- }
-
- elseif (tCharCode=4) {
- do AddLeaf
- set tNegateNext = 1
- }
-
- // skip if uninteresting
- else { set tCurrent=tCurrent_$e(pLogic,tPos) continue }
- }
- quit:$$$ISERR(tSC)
- do AddLeaf
-
- } catch (ex) {
- set tSC = ex.AsStatus()
- }
- quit tSC
-
-AddLeaf
- set tCurrent = $zstrip(tCurrent,"<>W")
- if tCurrent'="" {
- if '..NameIdxExists(pDomainId, tCurrent) {
- set tSC = $$$ERROR($$$GeneralError, "Unknown set referenced in logic: '"_tCurrent_"'")
- quit
- }
- set pTree(tNode,"leaf",$i(pTree(tNode,"leaf"))) = tCurrent
- set:tNegateNext pTree(tNode,"leaf",pTree(tNode,"leaf"),"negated") = 1
- set tCurrent = ""
- }
-}
-
-Method GetEntities() As %ListOfDataTypes
-{
- set tList = ..Entities
- if (..Logic'="") {
- do ..ParseLogic(..DomainId, ..Logic, .tTree)
- for i = 0:1:tTree {
- for j = 1:1:$g(tTree(i,"leaf")) {
- set tSetName = tTree(i,"leaf",j)
- set tSet = ..NameIdxOpen(..DomainId, tSetName)
- set tEntities = tSet.GetEntities()
- for k = 1:1:tEntities.Count() {
- do tList.Insert(tEntities.GetAt(k))
- }
- }
- }
- }
- quit tList
-}
-
-Method GetCRCs() As %ListOfDataTypes
-{
- set tList = ..CRCs
- if (..Logic'="") {
- do ..ParseLogic(..DomainId, ..Logic, .tTree)
- for i = 0:1:tTree {
- for j = 1:1:$g(tTree(i,"leaf")) {
- set tSetName = tTree(i,"leaf",j)
- set tSet = ..NameIdxOpen(..DomainId, tSetName)
- set tCRCs = tSet.GetCRCs()
- for k = 1:1:tCRCs.Count() {
- do tList.Insert(tCRCs.GetAt(k))
- }
- }
- }
- }
- quit tList
-}
-
-Storage Default
-{
-
-
-%%CLASSNAME
-
-
-DomainId
-
-
-Name
-
-
-Entities
-
-
-Logic
-
-
-CRCs
-
-
-^Demo.SetAnalEB18.SetDefinitionD
-SetDefinitionDefaultData
-100000
-^Demo.SetAnalEB18.SetDefinitionD
-^Demo.SetAnalEB18.SetDefinitionI
-^Demo.SetAnalEB18.SetDefinitionS
-%Storage.Persistent
-}
-
-}
+/// This class represents sets saved from the SetAnalysis demo application.
+Class Demo.SetAnalysis.SetDefinition Extends %Persistent
+{
+
+Property DomainId As %Integer;
+
+Property Name As %String;
+
+Property Entities As list Of %String(MAXLEN = "");
+
+Property CRCs As list Of %String(MAXLEN = "");
+
+Property Logic As %String(MAXLEN = 2000);
+
+Property Type As %String [ Calculated, ReadOnly, SqlComputeCode = { set {*} = $s({Logic}'="":"composite", 1:"entities")}, SqlComputed ];
+
+Index NameIdx On (DomainId, Name) [ Unique ];
+
+Index EntitiesIdx On (DomainId, Entities(ELEMENTS)) [ Type = bitmap ];
+
+Index CRCsIdx On (DomainId, CRCs(ELEMENTS)) [ Type = bitmap ];
+
+Method GetSDFilter() As SetDefinitionFilter
+{
+ quit ##class(SetDefinitionFilter).%New(..DomainId,..Name)
+}
+
+/// Retrieves a %iKnow.Filters.Filter instance representing all the sources
+/// in this set.
+Method GetFilter() As %iKnow.Filters.Filter
+{
+ if (..Logic="") {
+ set tEntities = ""
+ for i = 1:1:..Entities.Count() {
+ set tEntities = tEntities _ $lb(..Entities.GetAt(i))
+ }
+ if tEntities="" {
+ set tEntityFilter = ""
+ } else {
+ set tEntityFilter = ##class(%iKnow.Filters.ContainsEntityFilter).%New(..DomainId, .tEntities)
+ }
+ if '..CRCs.Count() {
+ quit tEntityFilter
+ }
+
+ // if we still have to filter by CRCs, create a SourceIdFilter
+ set tAllCRCs = ""
+ for i = 1:1:..CRCs.Count() {
+ set tValue = $lfs(..CRCs.GetAt(i)," ~ ")
+ set tAllCRCs = tAllCRCs_$lb(tValue)
+ }
+ do ##class(%iKnow.Queries.SourceAPI).GetByCrcs(.tResult, ..DomainId, tAllCRCs, 0, 0)
+ set i = ""
+ for {
+ set i = $o(tResult(i),1,tData)
+ quit:i=""
+ set tAllSources(+$lg(tData,1))=""
+ }
+ set tCRCFilter = ##class(%iKnow.Filters.SourceIdFilter).%New(..DomainId, .tAllSources)
+ if (tEntityFilter="") {
+ quit tCRCFilter
+ } else {
+ set tFilter = ##class(%iKnow.Filters.GroupFilter).%New(..DomainId, "OR")
+ do tFilter.AddSubFilter(tEntityFilter)
+ do tFilter.AddSubFilter(tCRCFilter)
+ quit tFilter
+ }
+
+ } else {
+
+ set tSC = ..ParseLogic(..DomainId, ..Logic, .tTree)
+ if $$$ISERR(tSC) { $$$ThrowStatus(tSC) }
+ for tNode = tTree:-1:0 {
+ set tOperator = $g(tTree(tNode,"operator"),"AND")
+ set tNegated = $g(tTree(tNode,"negated"), 0)
+ set tFilters(tNode) = ##class(%iKnow.Filters.GroupFilter).%New(..DomainId, tOperator, tNegated)
+ set tChild = ""
+ for {
+ set tChild = $o(tTree(tNode,"children",tChild))
+ quit:tChild=""
+ do tFilters(tNode).AddSubFilter(tFilters(tChild))
+ }
+ for tLeaf = 1:1:$g(tTree(tNode,"leaf")) {
+ if $d(tTree(tNode,"leaf",tLeaf,"negated")) {
+ set tLeafFilter = ##class(%iKnow.Filters.GroupFilter).%New(..DomainId, "AND", 1)
+ do tLeafFilter.AddSubFilter(..NameIdxOpen(..DomainId, tTree(tNode,"leaf",tLeaf)).GetFilter())
+ } else {
+ set tLeafFilter = ..NameIdxOpen(..DomainId, tTree(tNode,"leaf",tLeaf)).GetFilter()
+ }
+ do tFilters(tNode).AddSubFilter(tLeafFilter)
+ }
+ }
+ quit tFilters(0)
+ }
+}
+
+ClassMethod NameIsValid(pName As %String) As %Status
+{
+ quit:$zstrip(pName,"<>W")'=pName $$$ERROR($$$GeneralError,"Set name cannot have leading or trailing whitespace")
+ quit:$f(pName,"(")+$f(pName,")") $$$ERROR($$$GeneralError,"Set name cannot have parentheses")
+ quit:$zstrip(pName,"*C")'=pName $$$ERROR($$$GeneralError,"Set name cannot contain control characters")
+ quit:$find(" "_$$$UPPER(pName)_" "," AND ") $$$ERROR($$$GeneralError,"Set name cannot contain reserved word AND")
+ quit:$find(" "_$$$UPPER(pName)_" "," OR ") $$$ERROR($$$GeneralError,"Set name cannot contain reserved word OR")
+ quit:$find(" "_$$$UPPER(pName)_" "," NOT ") $$$ERROR($$$GeneralError,"Set name cannot contain reserved word NOT")
+ quit $$$OK
+}
+
+Method %OnValidateObject() As %Status [ Private, ServerOnly = 1 ]
+{
+ quit:(..Logic'="")&&..Entities.Count() $$$ERROR($$$GeneralError,"A set cannot be both based on entities and other sets")
+ quit ..ParseLogic(..DomainId, ..Logic)
+}
+
+ClassMethod ParseLogic(pDomainId As %Integer, pLogic As %String, Output pTree) As %Status [ Private ]
+{
+ kill pTree
+ set tSC = $$$OK, pTree=0
+ try {
+ set pLogic = $replace($replace(pLogic,")"," ) "),"("," ( ")
+ set pLogic = $zstrip($zstrip(pLogic,"=W"),"*C")
+ set tAnnotated = $translate($$$UPPER(pLogic),"()",$c(0,1))
+ set tAnnotated = $replace(tAnnotated," AND "," "_$c(2,2,2)_" ")
+ set tAnnotated = $replace(tAnnotated," OR "," "_$c(3,3)_" ")
+ set tAnnotated = $replace(tAnnotated," NOT "," "_$c(4,4,4)_" ")
+
+ set tPos=0, tEndPos = $l(pLogic), tCurrent="", tNode=0, tNegateNext=0
+ while $i(tPos)<=tEndPos {
+ set tChar = $e(tAnnotated,tPos), tCharCode=$a(tChar)
+
+ // opening parentheses: start new node
+ if (tCharCode=0) {
+ do AddLeaf
+ set pTree($i(pTree),"parent")=tNode
+ set pTree(tNode,"children",pTree)=""
+ set tNode = pTree
+ set:tNegateNext pTree(tNode,"negated")=1, tNegateNext=0
+ continue
+ }
+
+ // close parentheses: end current node and go back up
+ elseif (tCharCode=1) {
+ do AddLeaf
+ set:'$d(pTree(tNode,"operator")) pTree(tNode,"operator") = "AND"
+ set tNode = $g(pTree(tNode,"parent"),-1)
+ if (tNode<0) {
+ set tSC = $$$ERROR($$$GeneralError, "Illegal combination of sets, check parentheses")
+ quit
+ }
+ continue
+ }
+
+ // operator: AND
+ elseif (tCharCode=2) {
+ do AddLeaf
+ if $d(pTree(tNode,"operator"),tPrevOperator) && (tPrevOperator'="AND") {
+ set tSC = $$$ERROR($$$GeneralError, "Cannot mix operators")
+ quit
+ }
+ set pTree(tNode,"operator") = "AND"
+ set tPos=tPos+3
+ }
+
+ // operator: OR
+ elseif (tCharCode=3) {
+ do AddLeaf
+ if $d(pTree(tNode,"operator"),tPrevOperator) && (tPrevOperator'="OR") {
+ set tSC = $$$ERROR($$$GeneralError, "Cannot mix operators")
+ quit
+ }
+ set pTree(tNode,"operator") = "OR"
+ set tPos=tPos+2
+ }
+
+ elseif (tCharCode=4) {
+ do AddLeaf
+ set tNegateNext = 1
+ }
+
+ // skip if uninteresting
+ else { set tCurrent=tCurrent_$e(pLogic,tPos) continue }
+ }
+ quit:$$$ISERR(tSC)
+ do AddLeaf
+
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit tSC
+
+AddLeaf
+ set tCurrent = $zstrip(tCurrent,"<>W")
+ if tCurrent'="" {
+ if '..NameIdxExists(pDomainId, tCurrent) {
+ set tSC = $$$ERROR($$$GeneralError, "Unknown set referenced in logic: '"_tCurrent_"'")
+ quit
+ }
+ set pTree(tNode,"leaf",$i(pTree(tNode,"leaf"))) = tCurrent
+ set:tNegateNext pTree(tNode,"leaf",pTree(tNode,"leaf"),"negated") = 1
+ set tCurrent = ""
+ }
+}
+
+Method GetEntities() As %ListOfDataTypes
+{
+ set tList = ..Entities
+ if (..Logic'="") {
+ do ..ParseLogic(..DomainId, ..Logic, .tTree)
+ for i = 0:1:tTree {
+ for j = 1:1:$g(tTree(i,"leaf")) {
+ set tSetName = tTree(i,"leaf",j)
+ set tSet = ..NameIdxOpen(..DomainId, tSetName)
+ set tEntities = tSet.GetEntities()
+ for k = 1:1:tEntities.Count() {
+ do tList.Insert(tEntities.GetAt(k))
+ }
+ }
+ }
+ }
+ quit tList
+}
+
+Method GetCRCs() As %ListOfDataTypes
+{
+ set tList = ..CRCs
+ if (..Logic'="") {
+ do ..ParseLogic(..DomainId, ..Logic, .tTree)
+ for i = 0:1:tTree {
+ for j = 1:1:$g(tTree(i,"leaf")) {
+ set tSetName = tTree(i,"leaf",j)
+ set tSet = ..NameIdxOpen(..DomainId, tSetName)
+ set tCRCs = tSet.GetCRCs()
+ for k = 1:1:tCRCs.Count() {
+ do tList.Insert(tCRCs.GetAt(k))
+ }
+ }
+ }
+ }
+ quit tList
+}
+
+Storage Default
+{
+
+
+%%CLASSNAME
+
+
+DomainId
+
+
+Name
+
+
+Entities
+
+
+Logic
+
+
+CRCs
+
+
+^Demo.SetAnalEB18.SetDefinitionD
+SetDefinitionDefaultData
+100000
+^Demo.SetAnalEB18.SetDefinitionD
+^Demo.SetAnalEB18.SetDefinitionI
+^Demo.SetAnalEB18.SetDefinitionS
+%Storage.Persistent
+}
+
+}
+
diff --git a/src/cls/Demo/SetAnalysis/SetDefinitionFilter.cls b/src/cls/Demo/SetAnalysis/SetDefinitionFilter.cls
index 9d58a66..84c7941 100644
--- a/src/cls/Demo/SetAnalysis/SetDefinitionFilter.cls
+++ b/src/cls/Demo/SetAnalysis/SetDefinitionFilter.cls
@@ -1,49 +1,50 @@
-Class Demo.SetAnalysis.SetDefinitionFilter Extends %iKnow.Filters.Filter [ Language = objectscript ]
-{
-
-Property SetName As %String;
-
-Method %OnNew(pDomainId As %Integer, pSetName As %String) As %Status [ Internal, ServerOnly = 1 ]
-{
- set i%DomainId = pDomainId
- set i%SetName = pSetName
- quit ..Initialize(0)
-}
-
-Method GetLabel() As %String
-{
- quit "Set: "_..SetName
-}
-
-ClassMethod RestoreFilterFromStringInternal(filterSpec As %String) As %iKnow.Filters.Filter
-{
- set domain = $piece(filterSpec, "|", 1)
- set name = $piece(filterSpec, "|", 2,*)
- quit ..%New(domain, name)
-}
-
-Method ToString() As %String
-{
- quit ..%ClassName(1)_"|"_..DomainId_"|"_..SetName
-}
-
-/// This is the primary method that needs to be implemented by an actual %iKnow.Filters.Filter
-/// subclass to translate the abstract filter criteria the subclass addresses into a bitstring based on
-/// Source IDs. The subclass' implementation of this method should use SetSourceBits
-/// for this purpose, setting the requested bitstrings for each offset up to maxOffset.
-Method BuildSourceFilter(maxOffset As %Integer) As %Status [ Private ]
-{
- set tSetDef = ##class(Demo.SetAnalysis.SetDefinition).NameIdxOpen(..DomainId, ..SetName,, .tSC)
- quit:$$$ISERR(tSC) tSC
- #dim tFilter as %iKnow.Filters.Filter
- set tFilter = tSetDef.GetFilter()
- set i = ""
- for {
- set i = tFilter.GetNextSourceFilterOffset(i,.bits)
- quit:i=""
- do ..SetSourceBits(i,bits)
- }
- quit $$$OK
-}
-
-}
+Class Demo.SetAnalysis.SetDefinitionFilter Extends %iKnow.Filters.Filter [ Language = objectscript ]
+{
+
+Property SetName As %String;
+
+Method %OnNew(pDomainId As %Integer, pSetName As %String) As %Status [ Internal, ServerOnly = 1 ]
+{
+ set i%DomainId = pDomainId
+ set i%SetName = pSetName
+ quit ..Initialize(0)
+}
+
+Method GetLabel() As %String
+{
+ quit "Set: "_..SetName
+}
+
+ClassMethod RestoreFilterFromStringInternal(filterSpec As %String) As %iKnow.Filters.Filter
+{
+ set domain = $piece(filterSpec, "|", 1)
+ set name = $piece(filterSpec, "|", 2,*)
+ quit ..%New(domain, name)
+}
+
+Method ToString() As %String
+{
+ quit ..%ClassName(1)_"|"_..DomainId_"|"_..SetName
+}
+
+/// This is the primary method that needs to be implemented by an actual %iKnow.Filters.Filter
+/// subclass to translate the abstract filter criteria the subclass addresses into a bitstring based on
+/// Source IDs. The subclass' implementation of this method should use SetSourceBits
+/// for this purpose, setting the requested bitstrings for each offset up to maxOffset.
+Method BuildSourceFilter(maxOffset As %Integer) As %Status [ Private ]
+{
+ set tSetDef = ##class(Demo.SetAnalysis.SetDefinition).NameIdxOpen(..DomainId, ..SetName,, .tSC)
+ quit:$$$ISERR(tSC) tSC
+ #dim tFilter as %iKnow.Filters.Filter
+ set tFilter = tSetDef.GetFilter()
+ set i = ""
+ for {
+ set i = tFilter.GetNextSourceFilterOffset(i,.bits)
+ quit:i=""
+ do ..SetSourceBits(i,bits)
+ }
+ quit $$$OK
+}
+
+}
+
diff --git a/src/cls/Demo/SetAnalysis/Utils.cls b/src/cls/Demo/SetAnalysis/Utils.cls
index 1b37517..3d773bf 100644
--- a/src/cls/Demo/SetAnalysis/Utils.cls
+++ b/src/cls/Demo/SetAnalysis/Utils.cls
@@ -1,286 +1,287 @@
-Include %IKPublic
-
-Class Demo.SetAnalysis.Utils
-{
-
-/// Sets up your SetAnalysis demo, based on the data in column pDataColumn in table
-/// pTableName, using columns pMetadataColumns as additional metadata fields to
-/// visualize on the main demo page.
-/// First, this method will try to setup the REST web application using CreateRestWebApp.
-/// Then, it will create a domain definition matching the table and column information you provided.
-/// If needed, you can still modify that definition as you see fit, after which your domain will be built.
-/// Note that, if you already have a domain available, you'll only need to run the CreateRestWebApp
-/// method (once per namespace).
-ClassMethod Setup(pTableName As %String, pDataColumn As %String, pMetadataColumns As %List = "", ByRef pDomainName As %String = "") As %Status
-{
- set tSC = $$$OK
- try {
- do ..CreateRestWebApp(.tWebAppName)
-
- // some input cleansing
- set:pDomainName="" pDomainName = $translate(pTableName,"_."," ")
- set pDomainName = $zstrip(pDomainName,"*W")
- set:(pMetadataColumns'="")&&'$lv(pMetadataColumns) pMetadataColumns = $lfs(pMetadataColumns)
-
- // prepare metadata array tMetadata(FIELDNAME) = FIELDSPEC
- for i = 1:1:$ll(pMetadataColumns) {
- set tFieldSpec = $zstrip($lg(pMetadataColumns,i),"<>WP")
- continue:tFieldSpec=""
- set tAliased = $find($$$UPPER(tFieldSpec)," AS ")
- set tFieldName = $s(tAliased:$e(tFieldSpec,tAliased,*), 1:tFieldSpec)
- set tMetadata(tFieldName) = tFieldSpec
- }
-
- // set up domain
- set tSC = ..CreateDomainDefinition(pDomainName, pTableName, pDataColumn, .tMetadata, .tDomainDefClass)
- quit:$$$ISERR(tSC)
-
- } catch (ex) {
- set tSC = ex.AsStatus()
- }
-
- if $$$ISOK(tSC) {
-
- write !,"Demo setup completed succesfully.",!!,"You can now make any final modifications to "_tDomainDefClass_" (refine metadata or configuration,...).",!,"Just hit enter when you're done",!
-
- read tDummy
-
- set tSC = $classmethod(tDomainDefClass,"%Build")
-
- if $$$ISOK(tSC) {
- set tDomainId = $classmethod(tDomainDefClass, "%GetDomainId")
- do ##class(%Library.RoutineMgr).GetWebServerPort(.tPort,.tServer,.tURLPrefix,.tURL)
- write !,"You can now access your application at "_tURL_"csp/",$namespace,"/SetAnalysisDemo.csp?",tDomainId,!
- }
- } else {
- write !!,"Something went wrong setting up your demo:",!
- do $system.OBJ.DisplayError(tSC)
- }
-
- quit tSC
-}
-
-ClassMethod CreateDomainDefinition(pDomainName As %String, pTableName As %String, pDataColumn As %String, ByRef pMetadata, Output pDomainDefClass As %String = "") As %Status [ Internal ]
-{
- set tSC = $$$OK
- try {
- do $system.SQL.TableExists(pTableName,.tMetadata)
- set tClassName = $lg(tMetadata,3)
- set tPackageName = $piece(tClassName,".",1,*-1)
-
- set tDomainDef = ##class(%iKnow.Model.domain).%New()
- set tDomainDef.name = pDomainName
- //set tDomainDef.objectsPackage = tPackageName_".Tables" // helpful addition in 2015.2
-
- // set sort field to spread, as that's the metric being visualized
- set tParamDef = ##class(%iKnow.Model.parameter).%New()
- set tParamDef.name = $$$IKPSORTFIELD
- set tParamDef.value = $$$SORTBYSPREAD
- set tParamDef.parent = tDomainDef
-
- // add data location
- set tDomainDef.data = ##class(%iKnow.Model.data).%New()
- set tListDef = ##class(%iKnow.Model.listTable).%New()
- set tListDef.tableName = pTableName
- set tListDef.idField = "ID"
- set tListDef.groupField = "ID"
- set tListDef.dataFields = pDataColumn
- set tListDef.data = tDomainDef.data
-
- // add metadata
- set tDomainDef.metadata = ##class(%iKnow.Model.metadata).%New()
- set tFieldName = ""
- for {
- set tFieldName = $order(pMetadata(tFieldName), 1, tFieldSpec)
- quit:tFieldName=""
- set tListDef.metadataColumns = tListDef.metadataColumns _ $s(tListDef.metadataColumns="":"", 1:",") _ tFieldSpec
- //set tListDef.metadataFields = tListDef.metadataFields _ $s(tListDef.metadataFields="":"", 1:",") _ tFieldName
- set tFieldDef = ##class(%iKnow.Model.metadataField).%New()
- set tFieldDef.name = tFieldName
- set tFieldDef.metadata = tDomainDef.metadata
- }
-
- // language
-rdlang write !,"Which language are these texts in? [en] "
- read tLanguage
- if (tLanguage'="") && (tLanguage'="en") {
- set tConfig = ##class(%iKnow.Model.configuration).%New()
- set tConfig.name = pDomainName_".Config"
- set tConfig.languages = tLanguage
- set tSC = tConfig.%Validate()
- if $$$ISERR(tSC) {
- do $system.OBJ.DisplayError(tSC)
- goto rdlang
- }
- do tDomainDef.configurations.Insert(tConfig)
- set tParamDef = ##class(%iKnow.Model.parameter).%New()
- set tParamDef.name = $$$IKPDEFAULTCONFIG
- set tParamDef.value = tConfig.name
- set tParamDef.parent = tDomainDef
- }
- write !
-
- set pDomainDefClass = tPackageName_".Domain"
-
- if (($system.Version.GetMajor()*10)+$system.Version.GetMinor())>=20152 {
- // leverage utility methods in 2015.2+
- set tSC = tDomainDef.%SaveToClass(pDomainDefClass, 1, 1, 1)
- quit:$$$ISERR(tSC)
- } else {
- // otherwise do things manually
- if $$$defClassDefined(pDomainDefClass) {
- set tSC = $$Delete^%apiOBJ(pDomainDefClass)
- }
- set tClass = ##class(%Dictionary.ClassDefinition).%New()
- set tClass.Name = pDomainDefClass
- set tClass.Super = "%iKnow.DomainDefinition"
- set tClass.ProcedureBlock = 1
-
- // this is all taken care of inside %iKnow.Model.node after 2015.1!
- set tSC = tDomainDef.XMLExportToString(.tString)
- quit:$$$ISERR(tSC)
- set tString = ##class(%DeepSee.PMML.Builder.AbstractBuilder).FormatXML(tString)
- // avoid minor inconvenience with predefined readonly attribute
- set tString = $replace(tString, "listerClass=""%iKnow.Source.SQL.Lister""", "")
-
- set tXData = ##class(%Dictionary.XDataDefinition).%New()
- set tXData.Name = "Domain"
- set tXData.XMLNamespace = "http://www.intersystems.com/iknow"
- do tClass.XDatas.Insert(tXData)
- set tSC = tXData.Data.Write(tString)
- quit:$$$ISERR(tSC)
-
- set tSC = tClass.%Save()
- quit:$$$ISERR(tSC)
- set tClass="", tXData=""
-
- set tSC = $system.OBJ.Compile(pDomainDefClass, "ckd /multicompile=0")
- quit:$$$ISERR(tSC)
- }
-
- } catch (ex) {
- set tSC = ex.AsStatus()
- }
- quit tSC
-}
-
-/// Attempts to create a web application forwarding to Demo.SetAnalysis.RestHandler
-ClassMethod CreateRestWebApp(ByRef pWebAppName = "") As %Status
-{
- set tSC = $$$OK, tCreated=0, tCurrentNS = $$$LOWER($namespace)
- try {
- set:pWebAppName="" pWebAppName = "/csp/"_tCurrentNS_"/saREST/"
- set tProperties("NameSpace") = tCurrentNS
- set tProperties("DispatchClass") = "Demo.SetAnalysis.RestHandler"
- set tProperties("AutheEnabled") = $$$AutheUnauthenticated
- //set tProperties("iKnowEnabled") = 1
-
- zn "%SYS"
- if '##class(Security.Applications).Exists(pWebAppName) {
- set tSC = ##class(Security.Applications).Create(pWebAppName, .tProperties)
- quit:$$$ISERR(tSC)
- set tCreated=1
- }
-
- } catch (ex) {
- set tSC = ex.AsStatus()
- }
- zn tCurrentNS
-
- if $$$ISERR(tSC) {
- write !,"WARNING: unable to create web application due to the following error:",!
- do $system.OBJ.DisplayError(tSC)
- write !,"You'll still have to create a web application '",pWebAppName,"' referring to Demo.SetAnalysis.RestHandler",!
- } elseif (tCreated) {
- write !,"Web Application '"_pWebAppName_"' created successfully",!
- }
-
- quit $$$OK
-}
-
-ClassMethod ToClassifier(domainId As %Integer, setName As %String, classifierClassName As %String, metadataFieldName As %String, targetCategory As %String = "") As %Status
-{
- set sc = $$$OK
- try {
- set set = ##class(Demo.SetAnalysis.SetDefinition).NameIdxOpen(domainId, setName,, .sc)
- quit:'$isobject(set)
- set classifier = ##class(%iKnow.Classification.Definition.Classifier).%New()
- set classifier.description = "Automatically generated from set "_setName
-
- set param = ##class(%iKnow.Classification.Definition.BuilderParameter).%New()
- set param.name = "DomainId"
- set param.value = domainId
- do classifier.BuilderParameters.Insert(param)
- set param = ##class(%iKnow.Classification.Definition.BuilderParameter).%New()
- set param.name = "MetadataField"
- set param.value = metadataFieldName
- do classifier.BuilderParameters.Insert(param)
-
- // first build categories based on metadata field
- set sc = ##class(%iKnow.Queries.MetadataAPI).GetUniqueValues(.md, domainId, metadataFieldName, 0, 0)
- quit:$$$ISERR(sc)
- set i = ""
- for {
- set i = $order(md(i),1,d)
- quit:i=""
- set cat = ##class(%iKnow.Classification.Definition.Category).%New()
- set cat.name = $lg(d,1)
- set filter = ##class(%iKnow.Filters.SimpleMetadataFilter).%New(domainId, metadataFieldName, "=", cat.name)
- set cat.recordCount = filter.FilteredSourceCount
- set cat.spec = filter.ToString()
- do classifier.Categories.Insert(cat)
-
- set:targetCategory="" targetCategory = cat.name
- }
-
-
- set classifier.ClassificationMethod = ##class(%iKnow.Classification.Definition.ClassificationMethod).%New()
- set classifier.ClassificationMethod.method = "rules"
- set classifier.ClassificationMethod.ClassificationRules = ##class(%iKnow.Classification.Definition.ClassificationRules).%New()
-
- set rule = ##class(%iKnow.Classification.Definition.Rule).%New()
- set rule.category = targetCategory
- set rule.Predicate = ##class(%iKnow.Classification.Definition.PredicateOR).%New()
- do classifier.ClassificationMethod.ClassificationRules.Rules.Insert(rule)
-
- set classifier.TermDictionary = ##class(%iKnow.Classification.Definition.TermDictionary).%New()
- set entityCount = set.Entities.Count()
- for i = 1:1:entityCount {
- set term = ##class(%iKnow.Classification.Definition.TermEntity).%New()
- do term.Entries.Insert(set.Entities.GetAt(i))
- do classifier.TermDictionary.Terms.Insert(term)
-
- set predicate = ##class(%iKnow.Classification.Definition.Predicate).%New(),
- predicate.operator = "greaterThan",
- predicate.term = i,
- predicate.value = 0
- do rule.Predicate.predicates.Insert(predicate)
- }
-
- for i = 1:1:set.CRCs.Count() {
- set term = ##class(%iKnow.Classification.Definition.TermCRC).%New()
- set str = set.CRCs.GetAt(i),
- crc = ##class(%iKnow.Classification.Definition.TermCRCEntry).%New(),
- crc.Master = $p(str," ~ ",1),
- crc.Relation = $p(str," ~ ",2),
- crc.Slave = $p(str," ~ ",3)
- do term.Entries.Insert(crc)
- do classifier.TermDictionary.Terms.Insert(term)
-
- set predicate = ##class(%iKnow.Classification.Definition.Predicate).%New(),
- predicate.operator = "greaterThan",
- predicate.term = i+entityCount,
- predicate.value = 0
- do rule.Predicate.predicates.Insert(predicate)
- }
-
- set sc = classifier.%SaveToClass(classifierClassName, 1, 1)
- quit:$$$ISERR(sc)
-
- } catch (ex) {
- set sc = ex.AsStatus()
- }
- quit sc
-}
-
-}
+Include %IKPublic
+
+Class Demo.SetAnalysis.Utils
+{
+
+/// Sets up your SetAnalysis demo, based on the data in column pDataColumn in table
+/// pTableName, using columns pMetadataColumns as additional metadata fields to
+/// visualize on the main demo page.
+/// First, this method will try to setup the REST web application using CreateRestWebApp.
+/// Then, it will create a domain definition matching the table and column information you provided.
+/// If needed, you can still modify that definition as you see fit, after which your domain will be built.
+/// Note that, if you already have a domain available, you'll only need to run the CreateRestWebApp
+/// method (once per namespace).
+ClassMethod Setup(pTableName As %String, pDataColumn As %String, pMetadataColumns As %List = "", ByRef pDomainName As %String = "") As %Status
+{
+ set tSC = $$$OK
+ try {
+ do ..CreateRestWebApp(.tWebAppName)
+
+ // some input cleansing
+ set:pDomainName="" pDomainName = $translate(pTableName,"_."," ")
+ set pDomainName = $zstrip(pDomainName,"*W")
+ set:(pMetadataColumns'="")&&'$lv(pMetadataColumns) pMetadataColumns = $lfs(pMetadataColumns)
+
+ // prepare metadata array tMetadata(FIELDNAME) = FIELDSPEC
+ for i = 1:1:$ll(pMetadataColumns) {
+ set tFieldSpec = $zstrip($lg(pMetadataColumns,i),"<>WP")
+ continue:tFieldSpec=""
+ set tAliased = $find($$$UPPER(tFieldSpec)," AS ")
+ set tFieldName = $s(tAliased:$e(tFieldSpec,tAliased,*), 1:tFieldSpec)
+ set tMetadata(tFieldName) = tFieldSpec
+ }
+
+ // set up domain
+ set tSC = ..CreateDomainDefinition(pDomainName, pTableName, pDataColumn, .tMetadata, .tDomainDefClass)
+ quit:$$$ISERR(tSC)
+
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+
+ if $$$ISOK(tSC) {
+
+ write !,"Demo setup completed succesfully.",!!,"You can now make any final modifications to "_tDomainDefClass_" (refine metadata or configuration,...).",!,"Just hit enter when you're done",!
+
+ read tDummy
+
+ set tSC = $classmethod(tDomainDefClass,"%Build")
+
+ if $$$ISOK(tSC) {
+ set tDomainId = $classmethod(tDomainDefClass, "%GetDomainId")
+ do ##class(%Library.RoutineMgr).GetWebServerPort(.tPort,.tServer,.tURLPrefix,.tURL)
+ write !,"You can now access your application at "_tURL_"csp/",$namespace,"/SetAnalysisDemo.csp?",tDomainId,!
+ }
+ } else {
+ write !!,"Something went wrong setting up your demo:",!
+ do $system.OBJ.DisplayError(tSC)
+ }
+
+ quit tSC
+}
+
+ClassMethod CreateDomainDefinition(pDomainName As %String, pTableName As %String, pDataColumn As %String, ByRef pMetadata, Output pDomainDefClass As %String = "") As %Status [ Internal ]
+{
+ set tSC = $$$OK
+ try {
+ do $system.SQL.TableExists(pTableName,.tMetadata)
+ set tClassName = $lg(tMetadata,3)
+ set tPackageName = $piece(tClassName,".",1,*-1)
+
+ set tDomainDef = ##class(%iKnow.Model.domain).%New()
+ set tDomainDef.name = pDomainName
+ //set tDomainDef.objectsPackage = tPackageName_".Tables" // helpful addition in 2015.2
+
+ // set sort field to spread, as that's the metric being visualized
+ set tParamDef = ##class(%iKnow.Model.parameter).%New()
+ set tParamDef.name = $$$IKPSORTFIELD
+ set tParamDef.value = $$$SORTBYSPREAD
+ set tParamDef.parent = tDomainDef
+
+ // add data location
+ set tDomainDef.data = ##class(%iKnow.Model.data).%New()
+ set tListDef = ##class(%iKnow.Model.listTable).%New()
+ set tListDef.tableName = pTableName
+ set tListDef.idField = "ID"
+ set tListDef.groupField = "ID"
+ set tListDef.dataFields = pDataColumn
+ set tListDef.data = tDomainDef.data
+
+ // add metadata
+ set tDomainDef.metadata = ##class(%iKnow.Model.metadata).%New()
+ set tFieldName = ""
+ for {
+ set tFieldName = $order(pMetadata(tFieldName), 1, tFieldSpec)
+ quit:tFieldName=""
+ set tListDef.metadataColumns = tListDef.metadataColumns _ $s(tListDef.metadataColumns="":"", 1:",") _ tFieldSpec
+ //set tListDef.metadataFields = tListDef.metadataFields _ $s(tListDef.metadataFields="":"", 1:",") _ tFieldName
+ set tFieldDef = ##class(%iKnow.Model.metadataField).%New()
+ set tFieldDef.name = tFieldName
+ set tFieldDef.metadata = tDomainDef.metadata
+ }
+
+ // language
+rdlang write !,"Which language are these texts in? [en] "
+ read tLanguage
+ if (tLanguage'="") && (tLanguage'="en") {
+ set tConfig = ##class(%iKnow.Model.configuration).%New()
+ set tConfig.name = pDomainName_".Config"
+ set tConfig.languages = tLanguage
+ set tSC = tConfig.%Validate()
+ if $$$ISERR(tSC) {
+ do $system.OBJ.DisplayError(tSC)
+ goto rdlang
+ }
+ do tDomainDef.configurations.Insert(tConfig)
+ set tParamDef = ##class(%iKnow.Model.parameter).%New()
+ set tParamDef.name = $$$IKPDEFAULTCONFIG
+ set tParamDef.value = tConfig.name
+ set tParamDef.parent = tDomainDef
+ }
+ write !
+
+ set pDomainDefClass = tPackageName_".Domain"
+
+ if (($system.Version.GetMajor()*10)+$system.Version.GetMinor())>=20152 {
+ // leverage utility methods in 2015.2+
+ set tSC = tDomainDef.%SaveToClass(pDomainDefClass, 1, 1, 1)
+ quit:$$$ISERR(tSC)
+ } else {
+ // otherwise do things manually
+ if $$$defClassDefined(pDomainDefClass) {
+ set tSC = $$Delete^%apiOBJ(pDomainDefClass)
+ }
+ set tClass = ##class(%Dictionary.ClassDefinition).%New()
+ set tClass.Name = pDomainDefClass
+ set tClass.Super = "%iKnow.DomainDefinition"
+ set tClass.ProcedureBlock = 1
+
+ // this is all taken care of inside %iKnow.Model.node after 2015.1!
+ set tSC = tDomainDef.XMLExportToString(.tString)
+ quit:$$$ISERR(tSC)
+ set tString = ##class(%DeepSee.PMML.Builder.AbstractBuilder).FormatXML(tString)
+ // avoid minor inconvenience with predefined readonly attribute
+ set tString = $replace(tString, "listerClass=""%iKnow.Source.SQL.Lister""", "")
+
+ set tXData = ##class(%Dictionary.XDataDefinition).%New()
+ set tXData.Name = "Domain"
+ set tXData.XMLNamespace = "http://www.intersystems.com/iknow"
+ do tClass.XDatas.Insert(tXData)
+ set tSC = tXData.Data.Write(tString)
+ quit:$$$ISERR(tSC)
+
+ set tSC = tClass.%Save()
+ quit:$$$ISERR(tSC)
+ set tClass="", tXData=""
+
+ set tSC = $system.OBJ.Compile(pDomainDefClass, "ckd /multicompile=0")
+ quit:$$$ISERR(tSC)
+ }
+
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ quit tSC
+}
+
+/// Attempts to create a web application forwarding to Demo.SetAnalysis.RestHandler
+ClassMethod CreateRestWebApp(ByRef pWebAppName = "") As %Status
+{
+ set tSC = $$$OK, tCreated=0, tCurrentNS = $$$LOWER($namespace)
+ try {
+ set:pWebAppName="" pWebAppName = "/csp/"_tCurrentNS_"/saREST/"
+ set tProperties("NameSpace") = tCurrentNS
+ set tProperties("DispatchClass") = "Demo.SetAnalysis.RestHandler"
+ set tProperties("AutheEnabled") = $$$AutheUnauthenticated
+ //set tProperties("iKnowEnabled") = 1
+
+ zn "%SYS"
+ if '##class(Security.Applications).Exists(pWebAppName) {
+ set tSC = ##class(Security.Applications).Create(pWebAppName, .tProperties)
+ quit:$$$ISERR(tSC)
+ set tCreated=1
+ }
+
+ } catch (ex) {
+ set tSC = ex.AsStatus()
+ }
+ zn tCurrentNS
+
+ if $$$ISERR(tSC) {
+ write !,"WARNING: unable to create web application due to the following error:",!
+ do $system.OBJ.DisplayError(tSC)
+ write !,"You'll still have to create a web application '",pWebAppName,"' referring to Demo.SetAnalysis.RestHandler",!
+ } elseif (tCreated) {
+ write !,"Web Application '"_pWebAppName_"' created successfully",!
+ }
+
+ quit $$$OK
+}
+
+ClassMethod ToClassifier(domainId As %Integer, setName As %String, classifierClassName As %String, metadataFieldName As %String, targetCategory As %String = "") As %Status
+{
+ set sc = $$$OK
+ try {
+ set set = ##class(Demo.SetAnalysis.SetDefinition).NameIdxOpen(domainId, setName,, .sc)
+ quit:'$isobject(set)
+ set classifier = ##class(%iKnow.Classification.Definition.Classifier).%New()
+ set classifier.description = "Automatically generated from set "_setName
+
+ set param = ##class(%iKnow.Classification.Definition.BuilderParameter).%New()
+ set param.name = "DomainId"
+ set param.value = domainId
+ do classifier.BuilderParameters.Insert(param)
+ set param = ##class(%iKnow.Classification.Definition.BuilderParameter).%New()
+ set param.name = "MetadataField"
+ set param.value = metadataFieldName
+ do classifier.BuilderParameters.Insert(param)
+
+ // first build categories based on metadata field
+ set sc = ##class(%iKnow.Queries.MetadataAPI).GetUniqueValues(.md, domainId, metadataFieldName, 0, 0)
+ quit:$$$ISERR(sc)
+ set i = ""
+ for {
+ set i = $order(md(i),1,d)
+ quit:i=""
+ set cat = ##class(%iKnow.Classification.Definition.Category).%New()
+ set cat.name = $lg(d,1)
+ set filter = ##class(%iKnow.Filters.SimpleMetadataFilter).%New(domainId, metadataFieldName, "=", cat.name)
+ set cat.recordCount = filter.FilteredSourceCount
+ set cat.spec = filter.ToString()
+ do classifier.Categories.Insert(cat)
+
+ set:targetCategory="" targetCategory = cat.name
+ }
+
+
+ set classifier.ClassificationMethod = ##class(%iKnow.Classification.Definition.ClassificationMethod).%New()
+ set classifier.ClassificationMethod.method = "rules"
+ set classifier.ClassificationMethod.ClassificationRules = ##class(%iKnow.Classification.Definition.ClassificationRules).%New()
+
+ set rule = ##class(%iKnow.Classification.Definition.Rule).%New()
+ set rule.category = targetCategory
+ set rule.Predicate = ##class(%iKnow.Classification.Definition.PredicateOR).%New()
+ do classifier.ClassificationMethod.ClassificationRules.Rules.Insert(rule)
+
+ set classifier.TermDictionary = ##class(%iKnow.Classification.Definition.TermDictionary).%New()
+ set entityCount = set.Entities.Count()
+ for i = 1:1:entityCount {
+ set term = ##class(%iKnow.Classification.Definition.TermEntity).%New()
+ do term.Entries.Insert(set.Entities.GetAt(i))
+ do classifier.TermDictionary.Terms.Insert(term)
+
+ set predicate = ##class(%iKnow.Classification.Definition.Predicate).%New(),
+ predicate.operator = "greaterThan",
+ predicate.term = i,
+ predicate.value = 0
+ do rule.Predicate.predicates.Insert(predicate)
+ }
+
+ for i = 1:1:set.CRCs.Count() {
+ set term = ##class(%iKnow.Classification.Definition.TermCRC).%New()
+ set str = set.CRCs.GetAt(i),
+ crc = ##class(%iKnow.Classification.Definition.TermCRCEntry).%New(),
+ crc.Master = $p(str," ~ ",1),
+ crc.Relation = $p(str," ~ ",2),
+ crc.Slave = $p(str," ~ ",3)
+ do term.Entries.Insert(crc)
+ do classifier.TermDictionary.Terms.Insert(term)
+
+ set predicate = ##class(%iKnow.Classification.Definition.Predicate).%New(),
+ predicate.operator = "greaterThan",
+ predicate.term = i+entityCount,
+ predicate.value = 0
+ do rule.Predicate.predicates.Insert(predicate)
+ }
+
+ set sc = classifier.%SaveToClass(classifierClassName, 1, 1)
+ quit:$$$ISERR(sc)
+
+ } catch (ex) {
+ set sc = ex.AsStatus()
+ }
+ quit sc
+}
+
+}
+