From 7835c5e9b2ff09a214ff1ed7a9c51eb61f687696 Mon Sep 17 00:00:00 2001 From: SergeyMi37 Date: Thu, 1 Sep 2022 15:09:34 +0300 Subject: [PATCH 1/2] added zpm support --- module.xml | 23 + src/cls/Demo/Hotels/DomainDef.cls | 161 +- src/cls/Demo/Hotels/Review.cls | 185 +- src/cls/Demo/Hotels/Tables/CcUnique.cls | 87 + src/cls/Demo/Hotels/Tables/CrcInSource.cls | 49 + src/cls/Demo/Hotels/Tables/CrcOccurrence.cls | 97 + src/cls/Demo/Hotels/Tables/CrcUnique.cls | 130 ++ src/cls/Demo/Hotels/Tables/Dictionary.cls | 52 + src/cls/Demo/Hotels/Tables/DictionaryItem.cls | 67 + .../Demo/Hotels/Tables/DictionaryMatch.cls | 151 ++ src/cls/Demo/Hotels/Tables/DictionaryTerm.cls | 55 + src/cls/Demo/Hotels/Tables/EntityInSource.cls | 61 + src/cls/Demo/Hotels/Tables/EntityUnique.cls | 85 + src/cls/Demo/Hotels/Tables/Part.cls | 124 ++ src/cls/Demo/Hotels/Tables/Path.cls | 73 + src/cls/Demo/Hotels/Tables/PathAttribute.cls | 44 + src/cls/Demo/Hotels/Tables/Sentence.cls | 82 + .../Demo/Hotels/Tables/SentenceAttribute.cls | 44 + src/cls/Demo/Hotels/Tables/Source.cls | 119 ++ src/cls/Demo/Hotels/TestCube.cls | 95 +- .../Demo/SetAnalysis/ComputedDimension.cls | 241 +-- src/cls/Demo/SetAnalysis/KnowledgePortal.cls | 123 +- src/cls/Demo/SetAnalysis/RestHandler.cls | 1799 +++++++++-------- src/cls/Demo/SetAnalysis/SetDefinition.cls | 545 ++--- .../Demo/SetAnalysis/SetDefinitionFilter.cls | 99 +- src/cls/Demo/SetAnalysis/Utils.cls | 573 +++--- 26 files changed, 3258 insertions(+), 1906 deletions(-) create mode 100644 module.xml create mode 100644 src/cls/Demo/Hotels/Tables/CcUnique.cls create mode 100644 src/cls/Demo/Hotels/Tables/CrcInSource.cls create mode 100644 src/cls/Demo/Hotels/Tables/CrcOccurrence.cls create mode 100644 src/cls/Demo/Hotels/Tables/CrcUnique.cls create mode 100644 src/cls/Demo/Hotels/Tables/Dictionary.cls create mode 100644 src/cls/Demo/Hotels/Tables/DictionaryItem.cls create mode 100644 src/cls/Demo/Hotels/Tables/DictionaryMatch.cls create mode 100644 src/cls/Demo/Hotels/Tables/DictionaryTerm.cls create mode 100644 src/cls/Demo/Hotels/Tables/EntityInSource.cls create mode 100644 src/cls/Demo/Hotels/Tables/EntityUnique.cls create mode 100644 src/cls/Demo/Hotels/Tables/Part.cls create mode 100644 src/cls/Demo/Hotels/Tables/Path.cls create mode 100644 src/cls/Demo/Hotels/Tables/PathAttribute.cls create mode 100644 src/cls/Demo/Hotels/Tables/Sentence.cls create mode 100644 src/cls/Demo/Hotels/Tables/SentenceAttribute.cls create mode 100644 src/cls/Demo/Hotels/Tables/Source.cls diff --git a/module.xml b/module.xml new file mode 100644 index 0000000..85d2e87 --- /dev/null +++ b/module.xml @@ -0,0 +1,23 @@ + + + + + isc-iknow-setanalysis + 1.0.0 + About Set Analysis Demo app for InterSystems' iKnow technology + module + src + + + + + diff --git a/src/cls/Demo/Hotels/DomainDef.cls b/src/cls/Demo/Hotels/DomainDef.cls index 84a6857..a475390 100644 --- a/src/cls/Demo/Hotels/DomainDef.cls +++ b/src/cls/Demo/Hotels/DomainDef.cls @@ -1,80 +1,81 @@ -Class Demo.Hotels.DomainDef Extends %iKnow.DomainDefinition -{ - -///

An XML representation of the domain this class defines.

-///

For a detailed reference of the available elements and attributes, consult the class -/// reference for %iKnow.Model.domain and other classes in the %iKnow.Model -/// package.

-XData Domain [ XMLNamespace = "http://www.intersystems.com/iknow" ] -{ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -hotel -guest - - -} - -} +Class Demo.Hotels.DomainDef Extends %iKnow.DomainDefinition +{ + +///

An XML representation of the domain this class defines.

+///

For a detailed reference of the available elements and attributes, consult the class +/// reference for %iKnow.Model.domain and other classes in the %iKnow.Model +/// package.

+XData Domain [ XMLNamespace = "http://www.intersystems.com/iknow" ] +{ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +hotel +guest + + +} + +} + diff --git a/src/cls/Demo/Hotels/Review.cls b/src/cls/Demo/Hotels/Review.cls index 0544539..b0d356a 100644 --- a/src/cls/Demo/Hotels/Review.cls +++ b/src/cls/Demo/Hotels/Review.cls @@ -1,92 +1,93 @@ -Class Demo.Hotels.Review Extends %Persistent [ Not ProcedureBlock ] -{ - -Property Authorname As %String(MAXLEN = ""); - -Property DataOrigin As %String; - -Property Hotelname As %String(MAXLEN = ""); - -Property Input As %String; - -Property ResultNumber As %String; - -Property ResultRow As %String; - -Property Reviewdate As %String(MAXLEN = ""); - -Property Reviewscore As %String(MAXLEN = ""); - -Property Reviewtext As %String(MAXLEN = ""); - -Property Reviewtitle As %String(MAXLEN = ""); - -Property ReviewFull As %String [ Calculated, SqlComputeCode = { set {*} = {Reviewtitle} _ $c(13,10,13,10) _ {Reviewtext}}, SqlComputed ]; - -Property SourcePageURL As %String(MAXLEN = 500); - -Property Staydetails As %String(MAXLEN = ""); - -Property StayType As %String [ Calculated, SqlComputeCode = { set {*} = $s($f({Staydetails},"business"):"business", $f({Staydetails},"family"):"family", $f({Staydetails},"solo"):"solo", $f({Staydetails},"couple"):"couple", $f({Staydetails},"friends"):"friends", 1:"unknown")}, SqlComputed ]; - -Property StayMonth As %String [ Calculated, SqlComputeCode = { set {*} = $zstrip($p({Staydetails}," ",2,3),"<>PC")}, SqlComputed ]; - -Property StayDate As %Date [ Calculated, SqlComputeCode = { set {*} = $zdateh($piece({StayMonth}," ",1)_" 1,"_$piece({StayMonth}," ",2),9,,,,,,,$h) }, SqlComputed ]; - -Property Widget As %String; - -Storage Default -{ - - -%%CLASSNAME - - -Authorname - - -DataOrigin - - -Hotelname - - -Input - - -ResultNumber - - -ResultRow - - -Reviewdate - - -Reviewscore - - -Reviewtext - - -Reviewtitle - - -SourcePageURL - - -Staydetails - - -Widget - - -^Demo.Hotels.ReviewD -ReviewDefaultData -^Demo.Hotels.ReviewD -^Demo.Hotels.ReviewI -^Demo.Hotels.ReviewS -%Storage.Persistent -} - -} +Class Demo.Hotels.Review Extends %Persistent [ Not ProcedureBlock ] +{ + +Property Authorname As %String(MAXLEN = ""); + +Property DataOrigin As %String; + +Property Hotelname As %String(MAXLEN = ""); + +Property Input As %String; + +Property ResultNumber As %String; + +Property ResultRow As %String; + +Property Reviewdate As %String(MAXLEN = ""); + +Property Reviewscore As %String(MAXLEN = ""); + +Property Reviewtext As %String(MAXLEN = ""); + +Property Reviewtitle As %String(MAXLEN = ""); + +Property ReviewFull As %String [ Calculated, SqlComputeCode = { set {*} = {Reviewtitle} _ $c(13,10,13,10) _ {Reviewtext}}, SqlComputed ]; + +Property SourcePageURL As %String(MAXLEN = 500); + +Property Staydetails As %String(MAXLEN = ""); + +Property StayType As %String [ Calculated, SqlComputeCode = { set {*} = $s($f({Staydetails},"business"):"business", $f({Staydetails},"family"):"family", $f({Staydetails},"solo"):"solo", $f({Staydetails},"couple"):"couple", $f({Staydetails},"friends"):"friends", 1:"unknown")}, SqlComputed ]; + +Property StayMonth As %String [ Calculated, SqlComputeCode = { set {*} = $zstrip($p({Staydetails}," ",2,3),"<>PC")}, SqlComputed ]; + +Property StayDate As %Date [ Calculated, SqlComputeCode = { set {*} = $zdateh($piece({StayMonth}," ",1)_" 1,"_$piece({StayMonth}," ",2),9,,,,,,,$h) }, SqlComputed ]; + +Property Widget As %String; + +Storage Default +{ + + +%%CLASSNAME + + +Authorname + + +DataOrigin + + +Hotelname + + +Input + + +ResultNumber + + +ResultRow + + +Reviewdate + + +Reviewscore + + +Reviewtext + + +Reviewtitle + + +SourcePageURL + + +Staydetails + + +Widget + + +^Demo.Hotels.ReviewD +ReviewDefaultData +^Demo.Hotels.ReviewD +^Demo.Hotels.ReviewI +^Demo.Hotels.ReviewS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/CcUnique.cls b/src/cls/Demo/Hotels/Tables/CcUnique.cls new file mode 100644 index 0000000..72c37e7 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/CcUnique.cls @@ -0,0 +1,87 @@ +Class Demo.Hotels.Tables.CcUnique Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property CcUniId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property CorpusFrequency As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.CcUniDet(3,{CcUniId})),1)}, SqlComputed ]; + +Property CorpusSpread As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.CcUniDet(3,{CcUniId})),2)}, SqlComputed ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property Head As EntityUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {HeadId}}, SqlComputed ]; + +Property HeadId As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property Tail As EntityUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {TailId}}, SqlComputed ]; + +Property TailId As %Integer(MINVAL = 0) [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CcUni On (HeadId, TailId) [ Type = key, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CcUniExists [ Extent, Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CcUniId On CcUniId [ IdKey, PrimaryKey, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CcUniIdFreq On (CorpusFrequency As Minus, CcUniId); + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CcUniIdSpread On (CorpusSpread As Minus, CcUniId); + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniMToCcUniBit On HeadId [ Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniSToCcUniBit On TailId [ Type = bitmap ]; + +ForeignKey %HeadFK(HeadId) References EntityUnique() [ NoCheck ]; + +ForeignKey %TailFK(TailId) References EntityUnique() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + + +HeadId + + +TailId + + +^IRIS.IK.CcUniId(3) +CustomData +^IRIS.IK.CcUniId(3) + +^IRIS.IK.CcUni(3) + + +^IRIS.IK.CcUniExistsBit(3) + + +^IRIS.IK.CcUniIdFreq(3) + + +^IRIS.IK.CcUniIdSpread(3) + + +^IRIS.IK.EntUniMToCcUniBit(3) + + +^IRIS.IK.EntUniSToCcUniBit(3) + +^IRIS.IK.Idx.CCU(3) +^Demo.Hotels.Tables.CcUniqueS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/CrcInSource.cls b/src/cls/Demo/Hotels/Tables/CrcInSource.cls new file mode 100644 index 0000000..0c02a61 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/CrcInSource.cls @@ -0,0 +1,49 @@ +Class Demo.Hotels.Tables.CrcInSource Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property CrcUniId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property CrcUnique As CrcUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {CrcUniId}}, SqlComputed ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property Dominance As %Numeric [ ReadOnly ]; + +Property Frequency As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property Source As Source [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SourceId}}, SqlComputed ]; + +Property SourceId As %Integer(MINVAL = 1) [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CrcInSource On (SourceId, CrcUniId) [ IdKey, PrimaryKey, Unique ]; + +ForeignKey %CrcUniFK(CrcUniId) References CrcUnique() [ NoCheck ]; + +ForeignKey %SourceFK(SourceId) References Source() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + + +Frequency + + +Dominance + + +^IRIS.IK.CrcSrcDetails(3) +CustomData +^IRIS.IK.CrcSrcDetails(3) +^IRIS.IK.Idx.CSD(3) +^Demo.Hotels.Ta6B2A.CrcInSourceS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/CrcOccurrence.cls b/src/cls/Demo/Hotels/Tables/CrcOccurrence.cls new file mode 100644 index 0000000..b667ecd --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/CrcOccurrence.cls @@ -0,0 +1,97 @@ +Class Demo.Hotels.Tables.CrcOccurrence Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property CcUniId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {n crc set crc = $g(^IRIS.IK.CrcUniId(3,{CrcUniId})), {*} = $g(^IRIS.IK.CcUni(3,+$lg(crc,1),+$lg(crc,3)))}, SqlComputed ]; + +Property CcUnique As CcUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {CcUniId}}, SqlComputed ]; + +Property CrcOccId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property CrcUniId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property CrcUnique As CrcUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {CrcUniId}}, SqlComputed ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property HeadOccId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property PosInSentence As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property RelationOccId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property Sentence As Sentence [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SentenceId}}, SqlComputed ]; + +Property SentenceId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property Source As Source [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SourceId}}, SqlComputed ]; + +Property SourceId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.SentenceAPI).GetSourceId(3,{SentenceId})}, SqlComputed ]; + +Property TailOccId As %Integer(MINVAL = 1) [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CcUniToOccBit On CcUniId [ Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CrcOccId On CrcOccId [ IdKey, PrimaryKey, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CrcUniToOccBit On CrcUniId [ Type = bitmap ]; + +Index CrcOccExtent [ Extent, Type = bitmap ]; + +ForeignKey %CrcUniFK(CrcUniId) References CrcUnique() [ NoCheck ]; + +ForeignKey %EntOccHFK(HeadOccId) References Demo.Hotels.Tables.Part() [ NoCheck ]; + +ForeignKey %EntOccRFK(RelationOccId) References Demo.Hotels.Tables.Part() [ NoCheck ]; + +ForeignKey %EntOccTFK(TailOccId) References Demo.Hotels.Tables.Part() [ NoCheck ]; + +ForeignKey %SentenceFK(SentenceId) References Sentence() [ NoCheck ]; + +ForeignKey %SourceFK(SourceId) References Source() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + + +CrcUniId + + +HeadOccId + + +RelationOccId + + +TailOccId + + +SentenceId + + +PosInSentence + + +^IRIS.IK.CrcOccId(3) +CustomData +^IRIS.IK.CrcOccId(3) + +^IRIS.IK.CcUniToOccBit(3) + + +^IRIS.IK.CrcUniToOccBit(3) + +^IRIS.IK.Idx.CRCO(3) +^Demo.Hotels6B2A.CrcOccurrenceS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/CrcUnique.cls b/src/cls/Demo/Hotels/Tables/CrcUnique.cls new file mode 100644 index 0000000..b2daf58 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/CrcUnique.cls @@ -0,0 +1,130 @@ +Class Demo.Hotels.Tables.CrcUnique Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property CcUniId As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $g(^IRIS.IK.CcUni(3,+{HeadId},+{TailId}))}, SqlComputed ]; + +Property CcUnique As CcUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {CcUniId}}, SqlComputed ]; + +Property CorpusDominance As %Numeric [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Semantics.DominanceAPI).GetDomainValue(3,{CrcUniId},$$$SDCRC)}, SqlComputed ]; + +Property CorpusFrequency As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.CrcUniDetails(3,{CrcUniId})),1)}, SqlComputed ]; + +Property CorpusSpread As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.CrcUniDetails(3,{CrcUniId})),2)}, SqlComputed ]; + +Property CrcUniId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property Entities As %List [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $g(^IRIS.IK.CrcUniId(3,{CrcUniId}))}, SqlComputed ]; + +Property Head As EntityUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {HeadId}}, SqlComputed ]; + +Property HeadId As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property Relation As EntityUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {RelationId}}, SqlComputed ]; + +Property RelationId As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property Tail As EntityUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {TailId}}, SqlComputed ]; + +Property TailId As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property Value As %String(MAXLEN = "") [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $s({HeadId}:##class(EntityUnique).%OpenId({HeadId},0).EntityValue, 1:"") _ " ~ " _ $s({RelationId}:##class(EntityUnique).%OpenId({RelationId},0).EntityValue, 1:"") _ " ~ " _ $s({TailId}:##class(EntityUnique).%OpenId({TailId},0).EntityValue, 1:"")}, SqlComputed ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CrcUni On (HeadId, RelationId, TailId) [ Type = key, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CrcUniExists [ Extent, Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CrcUniId On CrcUniId [ IdKey, PrimaryKey, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CrcUniIdFreq On (CorpusFrequency As Minus, CrcUniId); + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %CrcUniIdSpread On (CorpusSpread As Minus, CrcUniId); + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniMToCrcUniBit On HeadId [ Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniRToCrcUniBit On RelationId [ Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniSToCrcUniBit On TailId [ Type = bitmap ]; + +ClassMethod EntitiesBuildValueArray(pEntities As %List, Output pArray As %String) As %Status +{ + set tSC = $$$OK + try { + kill pArray + set ptr = 0 + while $listnext(pEntities,ptr,tElement) { + continue:'tElement + set pArray(tElement) = $g(^IRIS.IK.EntUniId(3,tElement)) + } + } catch (ex) { + set tSC = ex.AsStatus() + } + quit tSC +} + +ForeignKey %CcUniqueFK(CcUniId) References Demo.Hotels.Tables.CcUnique() [ NoCheck ]; + +ForeignKey %HeadFK(HeadId) References EntityUnique() [ NoCheck ]; + +ForeignKey %RelationFK(RelationId) References EntityUnique() [ NoCheck ]; + +ForeignKey %TailFK(TailId) References EntityUnique() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + + +HeadId + + +RelationId + + +TailId + + +^IRIS.IK.CrcUniId(3) +CustomData +^IRIS.IK.CrcUniId(3) + +^IRIS.IK.CrcUni(3) + + +^IRIS.IK.CrcUniExistsBit(3) + + +^IRIS.IK.CrcUniIdFreq(3) + + +^IRIS.IK.CrcUniIdSpread(3) + + +^IRIS.IK.EntUniMToCrcUniBit(3) + + +^IRIS.IK.EntUniRToCrcUniBit(3) + + +^IRIS.IK.EntUniSToCrcUniBit(3) + +^IRIS.IK.Idx.CRCU(3) +^Demo.Hotels.Tables.CrcUniqueS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/Dictionary.cls b/src/cls/Demo/Hotels/Tables/Dictionary.cls new file mode 100644 index 0000000..e5af84b --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/Dictionary.cls @@ -0,0 +1,52 @@ +Class Demo.Hotels.Tables.Dictionary Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property DefaultLanguage As %String(MAXLEN = 150) [ ReadOnly ]; + +Property Description As %String(MAXLEN = "") [ ReadOnly ]; + +Property DictionaryId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property Name As %String(MAXLEN = 1000) [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %DictName On Name [ Type = key, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %DictionaryId On DictionaryId [ IdKey, PrimaryKey, Unique ]; + +Index DictExtent [ Extent, Type = bitmap ]; + +Storage iKnowStorage +{ + +"c" + + + +Name + + +Description + + +DefaultLanguage + + +^IRIS.IK.Mat.DictId(3) +CustomData +^IRIS.IK.Mat.DictId(3) + +^IRIS.IK.Mat.Dict(3) + +^IRIS.IK.Idx.MD(3) +^Demo.Hotels.Tables.DictionaryS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/DictionaryItem.cls b/src/cls/Demo/Hotels/Tables/DictionaryItem.cls new file mode 100644 index 0000000..dee7226 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/DictionaryItem.cls @@ -0,0 +1,67 @@ +Class Demo.Hotels.Tables.DictionaryItem Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property DefaultLanguage As %String(MAXLEN = 150) [ ReadOnly ]; + +Property Dictionary As Dictionary [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {DictionaryId}}, SqlComputed ]; + +Property DictionaryId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DictionaryItemId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property Name As %String(MAXLEN = 1000) [ ReadOnly ]; + +Property Terms As %List [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $g(^IRIS.IK.Mat.DictItemTerms(193,{DictionaryItemId}))}, SqlComputed ]; + +Property URI As %String(COLLATION = "EXACT", MAXLEN = 150) [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %DictItemURI On URI [ Type = key, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %DictToItem On DictionaryId; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %DictionaryItemId On DictionaryItemId [ IdKey, PrimaryKey, Unique ]; + +Index DictItemExtent [ Extent, Type = bitmap ]; + +Storage iKnowStorage +{ + +"c" + + + +DictionaryId + + +Name + + +URI + + +DefaultLanguage + + +^IRIS.IK.Mat.DictItemId(3) +CustomData +^IRIS.IK.Mat.DictItemId(3) + +^IRIS.IK.Mat.DictItemURI(3) + + +^IRIS.IK.Mat.DictToItem(3) + +^IRIS.IK.Idx.MDI(3) +^Demo.Hotels6B2A.DictionaryItemS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/DictionaryMatch.cls b/src/cls/Demo/Hotels/Tables/DictionaryMatch.cls new file mode 100644 index 0000000..f2ccff7 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/DictionaryMatch.cls @@ -0,0 +1,151 @@ +Class Demo.Hotels.Tables.DictionaryMatch Extends (%Persistent, %iKnow.Tables.AbstractDictionaryMatch) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property Dictionary As Dictionary [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {DictionaryId}}, SqlComputed ]; + +Property DictionaryId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DictionaryItem As DictionaryItem [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {DictionaryItemId}}, SqlComputed ]; + +Property DictionaryItemId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DictionaryTerm As DictionaryTerm [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {DictionaryTermId}}, SqlComputed ]; + +Property DictionaryTermId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property FirstPosInPath As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property IsInOrder As %Boolean(MINVAL = 1) [ ReadOnly ]; + +Property LastPosInPath As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property MatchId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property MatchedConceptCount As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property MatchedRelationCount As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property NegatedEntityCount As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property PartialMatchCount As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property Parts As %List [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(Demo.Hotels.Tables.DictionaryMatch).GetParts({MatchId})}, SqlComputed ]; + +Property Score As %Numeric(MINVAL = 1) [ ReadOnly ]; + +Property Sentence As Sentence [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SentenceId}}, SqlComputed ]; + +Property SentenceId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Matching.MatchingAPI).GetSentenceIdForMatchTarget(3,{TargetType},{TargetId})}, SqlComputed ]; + +Property Source As Source [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SourceId}}, SqlComputed ]; + +Property SourceId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Matching.MatchingAPI).GetSourceIdForMatchTarget(3,{TargetType},{TargetId})}, SqlComputed ]; + +Property TargetId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property TargetType As %Integer(MINVAL = 1) [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %DictToMatch On DictionaryId [ Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntOccToMatch On Parts(ELEMENTS); + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %ItemToMatch On DictionaryItemId; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %MatchId On MatchId [ IdKey, PrimaryKey, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %SourceToMatch On SourceId; + +Index DictMatchExtent [ Extent, Type = bitmap ]; + +ClassMethod PartsBuildValueArray(pEntities As %List, Output pArray As %String) As %Status +{ + set tSC = $$$OK + try { + kill pArray + set ptr = 0 + while $listnext(pEntities,ptr,tElement) { + set pArray(tElement) = "" + } + } catch (ex) { + set tSC = ex.AsStatus() + } + quit tSC +} + +Storage iKnowStorage +{ + +"c" + + + +DictionaryId + + +DictionaryItemId + + +DictionaryTermId + + +TargetType + + +TargetId + + +Score + + +MatchedConceptCount + + +MatchedRelationCount + + +PartialMatchCount + + +FirstPosInPath + + +LastPosInPath + + +IsInOrder + + +NegatedEntityCount + + +^IRIS.IK.Mat.MatchId(3) +CustomData +^IRIS.IK.Mat.MatchId(3) + +^IRIS.IK.Mat.DictToMatchBit(3) + + +^IRIS.IK.Mat.EntOccToMatch(3) + + +^IRIS.IK.Mat.DictItemToMatch(3) + + +^IRIS.IK.Mat.SrcToMatch(3) + +^IRIS.IK.Idx.MM(3) +^Demo.Hotel6B2A.DictionaryM44DAS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/DictionaryTerm.cls b/src/cls/Demo/Hotels/Tables/DictionaryTerm.cls new file mode 100644 index 0000000..173510d --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/DictionaryTerm.cls @@ -0,0 +1,55 @@ +Class Demo.Hotels.Tables.DictionaryTerm Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property DefaultLanguage As %String(MAXLEN = 150) [ ReadOnly ]; + +Property Dictionary As Dictionary [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {DictionaryId}}, SqlComputed ]; + +Property DictionaryId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DictionaryItem As DictionaryItem [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {DictionaryItemId}}, SqlComputed ]; + +Property DictionaryItemId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DictionaryTermId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property StringValue As %String(MAXLEN = "") [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %DictionaryTermId On DictionaryTermId [ IdKey, PrimaryKey, Unique ]; + +Index DictTermExtent [ Extent, Type = bitmap ]; + +Storage iKnowStorage +{ + +"c" + + + +DictionaryId + + +DictionaryItemId + + +StringValue + + +DefaultLanguage + + +^IRIS.IK.Mat.DictTermId(3) +CustomData +^IRIS.IK.Mat.DictTermId(3) +^IRIS.IK.Idx.MDT(3) +^Demo.Hotels6B2A.DictionaryTermS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/EntityInSource.cls b/src/cls/Demo/Hotels/Tables/EntityInSource.cls new file mode 100644 index 0000000..8d228ec --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/EntityInSource.cls @@ -0,0 +1,61 @@ +Class Demo.Hotels.Tables.EntityInSource Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property DominanceAsConcept As %Numeric [ ReadOnly ]; + +Property DominanceAsRelation As %Numeric [ ReadOnly ]; + +Property EntUniId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property Entity As EntityUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {EntUniId}}, SqlComputed ]; + +Property Frequency As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {FrequencyAsConcept} + {FrequencyAsRelation}}, SqlComputed ]; + +Property FrequencyAsConcept As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property FrequencyAsRelation As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property Source As Source [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SourceId}}, SqlComputed ]; + +Property SourceId As %Integer(MINVAL = 1) [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntityInSource On (SourceId, EntUniId) [ IdKey, PrimaryKey, Unique ]; + +ForeignKey %EntUniFK(EntUniId) References EntityUnique() [ NoCheck ]; + +ForeignKey %SourceFK(SourceId) References Source() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + + +FrequencyAsConcept + + +FrequencyAsRelation + + +DominanceAsConcept + + +DominanceAsRelation + + +^IRIS.IK.EntSrcDetails(3) +CustomData +^IRIS.IK.EntSrcDetails(3) +^IRIS.IK.Idx.ESD(3) +^Demo.Hotels6B2A.EntityInSourceS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/EntityUnique.cls b/src/cls/Demo/Hotels/Tables/EntityUnique.cls new file mode 100644 index 0000000..3f0c172 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/EntityUnique.cls @@ -0,0 +1,85 @@ +Class Demo.Hotels.Tables.EntityUnique Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property CorpusDominanceAsConcept As %Numeric [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Semantics.DominanceAPI).GetDomainValue(3,{EntUniId},$$$SDCONCEPT)}, SqlComputed ]; + +Property CorpusDominanceAsRelation As %Numeric [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Semantics.DominanceAPI).GetDomainValue(3,{EntUniId},$$$SDRELATION)}, SqlComputed ]; + +Property CorpusFrequency As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {CorpusFrequencyAsConcept} + {CorpusFrequencyAsRelation}}, SqlComputed ]; + +Property CorpusFrequencyAsConcept As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.EntUniDetails(3,{EntUniId})),1)}, SqlComputed ]; + +Property CorpusFrequencyAsRelation As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.EntUniDetails(3,{EntUniId})),2)}, SqlComputed ]; + +Property CorpusSpread As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.EntUniDetails(3,{EntUniId})),3)}, SqlComputed ]; + +Property CorpusSpreadAsConcept As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.EntUniDetails(3,{EntUniId})),4)}, SqlComputed ]; + +Property CorpusSpreadAsRelation As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.EntUniDetails(3,{EntUniId})),5)}, SqlComputed ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property EntUniId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property EntityValue As %String(COLLATION = "SQLSTRING", MAXLEN = "") [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUni On EntityValue [ Type = collatedkey, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniExists [ Extent, Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniFreqCon On CorpusFrequencyAsConcept As Minus; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniFreqRel On CorpusFrequencyAsRelation As Minus; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniId On EntUniId [ IdKey, PrimaryKey, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniSpreadCon On CorpusSpreadAsConcept As Minus; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniSpreadRel On CorpusSpreadAsRelation As Minus; + +Storage iKnowStorage +{ + +"c" + + +EntityValue +node + +^IRIS.IK.EntUniId(3) +CustomData +^IRIS.IK.EntUniId(3) + +^IRIS.IK.EntUni(3) + + +^IRIS.IK.EntUniExistsBit(3) + + +^IRIS.IK.EntUniIdFreq(3,0) + + +^IRIS.IK.EntUniIdFreq(3,1) + + +^IRIS.IK.EntUniIdSpread(3,0) + + +^IRIS.IK.EntUniIdSpread(3,1) + +^IRIS.IK.Idx.EU(3) +^Demo.Hotels.T6B2A.EntityUniqueS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/Part.cls b/src/cls/Demo/Hotels/Tables/Part.cls new file mode 100644 index 0000000..a2dc0ab --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/Part.cls @@ -0,0 +1,124 @@ +Class Demo.Hotels.Tables.Part Extends (%Persistent, %iKnow.Tables.AbstractPart) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property Annotations As %ArrayOfObjects [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(Demo.Hotels.Tables.Part).GetAnnotations({PartId})}, SqlComputed ]; + +Property Attributes As %ArrayOfObjects [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(Demo.Hotels.Tables.Part).GetAttributes({PartId})}, SqlComputed ]; + +Property CrcOccurrenceIdM As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property CrcOccurrenceIdR As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property CrcOccurrenceIdS As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property DictionaryMatches As %ArrayOfObjects [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(Demo.Hotels.Tables.Part).GetDictionaryMatches({PartId})}, SqlComputed ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property EntTypeId As %Integer(VALUELIST = "0,1,2,3") [ ReadOnly ]; + +Property EntUniId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property Entity As EntityUnique [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {EntUniId}}, SqlComputed ]; + +Property EntityType As %String [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $case({EntTypeId}, $$$ENTTYPECONCEPT:"concept", $$$ENTTYPERELATION:"relation", $$$ENTTYPENONREL:"non-relevant", $$$ENTTYPEPATHREL:"path-relevant", :"unknown")}, SqlComputed ]; + +Property EntityValue As %String(MAXLEN = "") [ Calculated, ReadOnly, SqlComputeCode = {new tObj if '{EntUniId} { set {*} = "" } else { set tObj = ##class(EntityUnique).%OpenId({EntUniId},0), {*} = $s($isobject(tObj):tObj.EntityValue, 1:"") }}, SqlComputed ]; + +Property Literal As %String(MAXLEN = "") [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.EntityAPI).GetLiteral(3,{PartId})}, SqlComputed ]; + +Property PartId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property Path As Path [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {PathId}}, SqlComputed ]; + +Property PathId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property PosInPath As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property PosInSentence As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property Sentence As Sentence [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SentenceId}}, SqlComputed ]; + +Property SentenceId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property Source As Source [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SourceId}}, SqlComputed ]; + +Property SourceId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.SentenceAPI).GetSourceId(3,{SentenceId})}, SqlComputed ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntTypeToOccBit On EntTypeId [ Type = bitslice ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniToOccBit On EntUniId [ Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %PartId On PartId [ IdKey, PrimaryKey, Unique ]; + +Index PartExtent [ Extent, Type = bitmap ]; + +ForeignKey %CrcOccMFK(CrcOccurrenceIdM) References Demo.Hotels.Tables.CrcOccurrence() [ NoCheck ]; + +ForeignKey %CrcOccRFK(CrcOccurrenceIdR) References Demo.Hotels.Tables.CrcOccurrence() [ NoCheck ]; + +ForeignKey %CrcOccSFK(CrcOccurrenceIdS) References Demo.Hotels.Tables.CrcOccurrence() [ NoCheck ]; + +ForeignKey %EntUniFK(EntUniId) References Demo.Hotels.Tables.EntityUnique() [ NoCheck ]; + +ForeignKey %PathFK(PathId) References Demo.Hotels.Tables.Path() [ NoCheck ]; + +ForeignKey %SentenceFK(SentenceId) References Demo.Hotels.Tables.Sentence() [ NoCheck ]; + +ForeignKey %SourceFK(SourceId) References Demo.Hotels.Tables.Source() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + + +EntUniId + + +EntTypeId + + +SentenceId + + +PosInSentence + + +CrcOccurrenceIdM + + +CrcOccurrenceIdR + + +CrcOccurrenceIdS + + +PathId + + +PosInPath + + +^IRIS.IK.EntOccId(3) +CustomData +^IRIS.IK.EntOccId(3) + +^IRIS.IK.EntTypeToOccBit(3) + + +^IRIS.IK.EntUniToOccBit(3) + +^IRIS.IK.Idx.EO(3) +^Demo.Hotels.Tables.PartS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/Path.cls b/src/cls/Demo/Hotels/Tables/Path.cls new file mode 100644 index 0000000..f86b9a5 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/Path.cls @@ -0,0 +1,73 @@ +Class Demo.Hotels.Tables.Path Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property Entities As %List [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.PathAPI).GetEntIds(3,{PathId})}, SqlComputed ]; + +Property EntityOccurrences As %List [ ReadOnly ]; + +Property PathId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property Sentence As Sentence [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SentenceId}}, SqlComputed ]; + +Property SentenceId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.PathAPI).GetSentenceId(3,{PathId})}, SqlComputed ]; + +Property Source As Source [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SourceId}}, SqlComputed ]; + +Property SourceId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.PathAPI).GetSourceId(3,{PathId})}, SqlComputed ]; + +Property Value As %String [ Calculated, ReadOnly, SqlComputeCode = {new tEntity,tEntList,tValue,tPointer set tEntList = {Entities}, tPointer=0, tValue="" while $listnext(tEntList,tPointer,tEntity) { set tValue = tValue _ $s(tValue="":"", 1:" ~ ") _ ##class(%iKnow.Queries.EntityAPI).GetValueInternal(3,tEntity) } set {*} = tValue}, SqlComputed ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniToPath On Entities(KEYS) [ Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %PathId On PathId [ IdKey, PrimaryKey, Unique ]; + +Index PathExtent [ Extent, Type = bitmap ]; + +ClassMethod EntitiesBuildValueArray(pEntities As %List, Output pArray As %String) As %Status +{ + set tSC = $$$OK + try { + kill pArray + set ptr = 0 + while $listnext(pEntities,ptr,tElement) { + continue:'tElement + set pArray(tElement) = $g(^IRIS.IK.EntUniId(3,tElement)) + } + } catch (ex) { + set tSC = ex.AsStatus() + } + quit tSC +} + +ForeignKey %SentenceFK(SentenceId) References Demo.Hotels.Tables.Sentence() [ NoCheck ]; + +ForeignKey %SourceFK(SourceId) References Demo.Hotels.Tables.Source() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + +EntityOccurrences +node + +^IRIS.IK.PathToEntOcc(3) +CustomData +^IRIS.IK.PathToEntOcc(3) + +^IRIS.IK.EntUniToPathBit(3) + +^IRIS.IK.Idx.Path(3) +^Demo.Hotels.Tables.PathS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/PathAttribute.cls b/src/cls/Demo/Hotels/Tables/PathAttribute.cls new file mode 100644 index 0000000..d9f5a27 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/PathAttribute.cls @@ -0,0 +1,44 @@ +Class Demo.Hotels.Tables.PathAttribute Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property AttributeTypeId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property Parts As %List [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $li($g(^IRIS.IK.PathToEntOcc(3,{PathId})),{StartPosInPath},{StartPosInPath}+{SpanInPath}-1)}, SqlComputed ]; + +Property Path As Path [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {PathId}}, SqlComputed ]; + +Property PathId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property SpanInPath As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property StartPosInPath As %Integer(MINVAL = 1) [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %PathAttribute On (PathId, AttributeTypeId, StartPosInPath) [ IdKey, PrimaryKey, Unique ]; + +ForeignKey %PathFK(PathId) References Path() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + + +SpanInPath + + +^IRIS.IK.Att.Path(3) +CustomData +^IRIS.IK.Att.Path(3) +^IRIS.IK.Idx.ATP(3) +^Demo.Hotels6B2A.PathAttributeS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/Sentence.cls b/src/cls/Demo/Hotels/Tables/Sentence.cls new file mode 100644 index 0000000..7bd296a --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/Sentence.cls @@ -0,0 +1,82 @@ +Class Demo.Hotels.Tables.Sentence Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property Entities As %List [ Calculated, ReadOnly, SqlComputeCode = {new tEntOccData,tEntOcc,tMaxEntOcc,tEntity,tList set tList="", tEntOccData = $g(^IRIS.IK.SentDetails(3,{SentenceId})),tEntOcc=$lg(tEntOccData,4),tMaxEntOcc=tEntOcc+$lg(tEntOccData,5),tEntOccData="" for { set tEntOcc=$o(^IRIS.IK.EntOccId(3,tEntOcc),1,tEntOccData) quit:tEntOcc="" quit:tEntOcc>tMaxEntOcc set tEntity=$lg(tEntOccData,1) set:tEntity tList=tList_$lb(tEntity) } set {*} = tList}, SqlComputed ]; + +Property LanguageConfidence As %Numeric [ ReadOnly ]; + +Property LanguageId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property Parts As %List [ Calculated, ReadOnly, SqlComputeCode = {new tSentData,tPartId,tMinPartId,tMaxPartId,tList set tList="", tSentData = $g(^IRIS.IK.SentDetails(3,{SentenceId})),tMinPartId=$lg(tSentData,4)+1,tMaxPartId=tMinPartId+$lg(tSentData,5)-1,tSentData="" for tPartId=tMinPartId:1:tMaxPartId { set tList=tList_$lb(tPartId) } set {*} = tList}, SqlComputed ]; + +Property Position As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.SentenceAPI).GetPosition(3,{SentenceId})}, SqlComputed ]; + +Property SentenceId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property SentenceValue As %String(COLLATION = "SQLUPPER(150)", MAXLEN = "") [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.SentenceAPI).GetValue(3,{SentenceId})}, SqlComputed ]; + +Property Source As Source [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SourceId}}, SqlComputed ]; + +Property SourceId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.SentenceAPI).GetSourceId(3,{SentenceId})}, SqlComputed ]; + +Property SummaryRelevance As %Numeric [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %EntUniToSent On Entities(KEYS) [ Type = bitmap ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %SentenceId On SentenceId [ IdKey, PrimaryKey, Unique ]; + +Index SentExtent [ Extent, Type = bitmap ]; + +ClassMethod EntitiesBuildValueArray(pEntities As %List, Output pArray As %String) As %Status +{ + set tSC = $$$OK + try { + kill pArray + set ptr = 0 + while $listnext(pEntities,ptr,tElement) { + continue:'tElement + set pArray(tElement) = $g(^IRIS.IK.EntUniId(3,tElement)) + } + } catch (ex) { + set tSC = ex.AsStatus() + } + quit tSC +} + +ForeignKey %SourceFK(SourceId) References Demo.Hotels.Tables.Source() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + + +LanguageId + + +LanguageConfidence + + +SummaryRelevance + + +^IRIS.IK.SentDetails(3) +CustomData +^IRIS.IK.SentDetails(3) + +^IRIS.IK.EntUniToSentBit(3) + +^IRIS.IK.Idx.Sent(3) +^Demo.Hotels.Tables.SentenceS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/SentenceAttribute.cls b/src/cls/Demo/Hotels/Tables/SentenceAttribute.cls new file mode 100644 index 0000000..b8d69d5 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/SentenceAttribute.cls @@ -0,0 +1,44 @@ +Class Demo.Hotels.Tables.SentenceAttribute Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property AttributeTypeId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property Parts As %List [ Calculated, ReadOnly, SqlComputeCode = {new tPartBase,tSentPos,tList,tAttData set tPartBase = $lg($g(^IRIS.IK.SentDetails(3,{SentenceId})),4),tList="",tAttData=$g(^IRIS.IK.Att.Sent(3,{SentenceId},{AttributeTypeId},{StartPosInSent})) for tSentPos=0:1:{SpanInSent}-1 { set:$ld(tAttData,tSentPos+2) tList=tList_$lb(tPartBase+{StartPosInSent}+tSentPos) } set {*} = tList}, SqlComputed ]; + +Property Sentence As Sentence [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {SentenceId}}, SqlComputed ]; + +Property SentenceId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property SpanInSent As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property StartPosInSent As %Integer(MINVAL = 1) [ ReadOnly ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %SentenceAttribute On (SentenceId, AttributeTypeId, StartPosInSent) [ IdKey, PrimaryKey, Unique ]; + +ForeignKey %SentenceFK(SentenceId) References Sentence() [ NoCheck ]; + +Storage iKnowStorage +{ + +"c" + + + +SpanInSent + + +^IRIS.IK.Att.Sent(3) +CustomData +^IRIS.IK.Att.Sent(3) +^IRIS.IK.Idx.ATS(3) +^Demo.Hotel6B2A.SentenceAttCA0AS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/Tables/Source.cls b/src/cls/Demo/Hotels/Tables/Source.cls new file mode 100644 index 0000000..f1eb816 --- /dev/null +++ b/src/cls/Demo/Hotels/Tables/Source.cls @@ -0,0 +1,119 @@ +Class Demo.Hotels.Tables.Source Extends (%Persistent, %iKnow.Tables.AbstractTable) [ Final, Inheritance = right, ProcedureBlock, StorageStrategy = iKnowStorage ] +{ + +Parameter DOMAINID = 3; + +Property Author As %String [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.MetadataAPI).GetValueById({DomainId},2,{SourceId})}, SqlComputed ]; + +Property AuthorIsTruncated As %Boolean [ Calculated, Internal, ReadOnly, SqlComputeCode = {set {*} = ($length({Author})>150)}, SqlComputed ]; + +Property CrcOccurrenceCount As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.SrcDetails(3,{SourceId})),6)}, SqlComputed ]; + +Property DomainId As %Integer(MINVAL = 1) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = 3}, SqlComputed ]; + +Property EntityOccurrenceCount As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.EntityAPI).GetOccurrenceCountBySource(3, {SourceId})}, SqlComputed ]; + +Property ExternalId As %String(MAXLEN = 1000) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.SourceAPI).GetExternalId(3, {SourceId})}, SqlComputed ]; + +Property FirstCrcOccurrenceId As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.SrcDetails(3,{SourceId})),5)+1}, SqlComputed ]; + +Property FirstPartId As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.SrcDetails(3,{SourceId})),3)+1}, SqlComputed ]; + +Property FirstPathId As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.SrcDetails(3,{SourceId})),7)+1}, SqlComputed ]; + +Property FirstSentenceId As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.SrcDetails(3,{SourceId})),1)+1}, SqlComputed ]; + +Property FullText As %String(MAXLEN = "") [ Calculated, ReadOnly, SqlComputeCode = {new tTxt,tFrom,tTo,tSentId,tOut,tMore s tTxt = "", tFrom=$lg($g(^IRIS.IK.SrcDetails(3,{SourceId})),1)+1, tTo=tFrom-1+$lg($g(^({SourceId})),2) for tSentId = tFrom:1:tTo { k tOut set tMore = ##class(%iKnow.Queries.SentenceAPI).GetValue(3,tSentId,.tOut) set tOut="" for { set tOut = $order(tOut(tOut),1,tMore) q:tOut="" set tTxt = tTxt _ tMore _ " " } } set {*} = $e(tTxt,1,*-1)}, SqlComputed ]; + +Property GroupId As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property GroupName As %String(MAXLEN = 150) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $g(^IRIS.IK.Ext.Group(3,{ListerId},{GroupId}))}, SqlComputed ]; + +Property ListerClass As %String(MAXLEN = 150) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $g(^IRIS.IK.Sys.ListerD({ListerId}))}, SqlComputed ]; + +Property ListerId As %Integer(MINVAL = 0) [ ReadOnly ]; + +Property LocalReference As %String(COLLATION = "EXACT", MAXLEN = 150) [ ReadOnly ]; + +Property PartCount As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.SrcDetails(3,{SourceId})),4)}, SqlComputed ]; + +Property PathCount As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.SrcDetails(3,{SourceId})),8)}, SqlComputed ]; + +Property Ref As Demo.Hotels.Review [ Calculated, ReadOnly, SqlComputeCode = {set {*} = {LocalReference}}, SqlComputed ]; + +Property SentenceCount As %Integer(MINVAL = 0) [ Calculated, ReadOnly, SqlComputeCode = {set {*} = $lg($g(^IRIS.IK.SrcDetails(3,{SourceId})),2)}, SqlComputed ]; + +Property SourceId As %Integer(MINVAL = 1) [ ReadOnly ]; + +Property StayMonth As %String [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.MetadataAPI).GetValueById({DomainId},4,{SourceId})}, SqlComputed ]; + +Property StayMonthIsTruncated As %Boolean [ Calculated, Internal, ReadOnly, SqlComputeCode = {set {*} = ($length({StayMonth})>150)}, SqlComputed ]; + +Property StayType As %String [ Calculated, ReadOnly, SqlComputeCode = {set {*} = ##class(%iKnow.Queries.MetadataAPI).GetValueById({DomainId},3,{SourceId})}, SqlComputed ]; + +Property StayTypeIsTruncated As %Boolean [ Calculated, Internal, ReadOnly, SqlComputeCode = {set {*} = ($length({StayType})>150)}, SqlComputed ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %ExtIdComp On (ListerId, GroupId, LocalReference) [ Type = key, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %MdtAuthor On (Author, AuthorIsTruncated); + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %MdtStayMonth On (StayMonth, StayMonthIsTruncated); + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %MdtStayType On (StayType, StayTypeIsTruncated); + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %SourceId On SourceId [ IdKey, PrimaryKey, Unique ]; + +/// This index is maintained automatically by iKnow. DO NOT MODIFY +Index %SrcExists [ Extent, Type = bitmap ]; + +ClassMethod SyncCustomizations(pAutoPurge As %Boolean = 1, pStartSrcId As %Integer = "", pEndSrcId As %Integer = "") As %Status [ SqlName = SyncCustomizations, SqlProc ] +{ + quit ##class(%iKnow.Tables.Utils).SyncCustomizations(..#DOMAINID,"Demo.Hotels.Tables",pAutoPurge,pStartSrcId,pEndSrcId) +} + +Storage iKnowStorage +{ + +"c" + + + +ListerId + + +GroupId + + +LocalReference + + +^IRIS.IK.SrcId(3) +CustomData +^IRIS.IK.SrcId(3) + +^IRIS.IK.Ext.LocalRef(3) + + +^IRIS.IK.Mdt.ValueToSrc(3,2) + + +^IRIS.IK.Mdt.ValueToSrc(3,4) + + +^IRIS.IK.Mdt.ValueToSrc(3,3) + + +^IRIS.IK.SrcExistsBit(3) + +^IRIS.IK.Idx.Src(3) +^Demo.Hotels.Tables.SourceS +%Storage.Persistent +} + +} + diff --git a/src/cls/Demo/Hotels/TestCube.cls b/src/cls/Demo/Hotels/TestCube.cls index 196e72a..0ba6da4 100644 --- a/src/cls/Demo/Hotels/TestCube.cls +++ b/src/cls/Demo/Hotels/TestCube.cls @@ -1,47 +1,48 @@ -/// -Class Demo.Hotels.TestCube Extends %DeepSee.CubeDefinition [ DependsOn = Demo.Hotels.Review, ProcedureBlock ] -{ - -/// Cube definition from Architect. -XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ] -{ - - - - - - - - - - - - -} - -Parameter DOMAIN; - -} +/// +Class Demo.Hotels.TestCube Extends %DeepSee.CubeDefinition [ DependsOn = Demo.Hotels.Review, ProcedureBlock ] +{ + +/// Cube definition from Architect. +XData Cube [ XMLNamespace = "http://www.intersystems.com/deepsee" ] +{ + + + + + + + + + + + + +} + +Parameter DOMAIN; + +} + diff --git a/src/cls/Demo/SetAnalysis/ComputedDimension.cls b/src/cls/Demo/SetAnalysis/ComputedDimension.cls index 80a2036..ed28baf 100644 --- a/src/cls/Demo/SetAnalysis/ComputedDimension.cls +++ b/src/cls/Demo/SetAnalysis/ComputedDimension.cls @@ -1,120 +1,121 @@ -Class Demo.SetAnalysis.ComputedDimension Extends %iKnow.DeepSee.Dimensions.Base -{ - -Method %ComputeIndexKey(pMemberKey As %String) As %String -{ - set:$f(pMemberKey,":") pMemberKey = $piece(pMemberKey,":",*) - Quit $ZCRC(pMemberKey,7) -} - -/// Method combining the functionality of %MemberSearch and -/// %OnGetComputedMembersFiltered to avoid having the same code twice.
-/// Returns entries of the form:
-/// pMembers(n) = $lb(id, name, key)
-/// Expects any predefined dimension members to supplied with pMemmbers upfront! -Method %OnGetComputedMembersInternal(ByRef pMembers, pSearchKey As %String = "", pRollupKey As %String = "", ByRef pRange As %String = "") As %Status [ Internal ] -{ - set tSC = $$$OK - try { - set tSQL = "SELECT ID, Name FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = ?" - set:pSearchKey'="" tSQL = tSQL_" AND Name LIKE '%"_pSearchKey_"%'" - set tStatement = ##class(%SQL.Statement).%New() - set tSC = tStatement.%Prepare(tSQL) - quit:$$$ISERR(tSC) - set tResult = tStatement.%Execute(..%ikDomainId) - while tResult.%Next() { - set pMembers($i(pMembers)) = $lb(tResult.%Get("Name"), tResult.%Get("Name"), tResult.%Get("Name")) - } - - } catch (ex) { - set tSC = ex.AsStatus() - } - quit tSC -} - -Method %FindComputedMemberByKey(pKey As %String, Output pFlag As %Boolean, Output pMemberName As %String, Output pMemberId As %String) As %Status -{ - set:$f(pKey,":") pKey = $piece(pKey,":",*) - set tSetObj = ##class(SetDefinition).NameIdxOpen(..%ikDomainId, pKey) - if $isobject(tSetObj) { - set pFlag=1, pMemberName=tSetObj.Name, pMemberId=pKey - } else { - set pFlag=0, pMemberName="", pMemberId="" - } - quit ..%ComputeBitset(pKey, .tIndexKey) -} - -/// Do the actual work of building the bitset. -Method %OnComputeBitset(pSpec As %String, pIndexKey As %String) As %Status -{ - set tSC = $$$OK - try { - set:$f(pSpec,":") pSpec = $piece(pSpec,":",*) - set tSetObj = ##class(SetDefinition).NameIdxOpen(..%ikDomainId, pSpec) - quit:tSetObj="" - - do tSetObj.GetFilter().ToBitstring(.tBits) - - kill $$$DeepSeeIndexGLVN(..%baseCube, ..%factNumber, pIndexKey) - merge $$$DeepSeeIndexGLVN(..%baseCube, ..%factNumber, pIndexKey) = tBits - - if (..%ikDomainType = "iKnow") { - set tIndexGlo = $name($$$DeepSeeIndexGLVN(..%baseCube, ..%factNumber, pIndexKey)) - set tSC = ##class(%iKnow.DeepSee.CubeUtils).TranslateIKnowBitstring(..%baseCube, ..%ikMeasure, tIndexGlo) - quit:$$$ISERR(tSC) - } - - } catch (ex) { - set tSC = ex.AsStatus() - } - quit tSC -} - -ClassMethod %Count(pCube As %String, pDimNo As %Integer, pHierNo As %Integer, pLevelNo As %Integer) As %Integer -{ - set tSC = $$$OK, tCount = 0 - try { - set tCube = $$$UPPER(pCube) - - // count number of pre-defined members - set tSC = ..%GetPredefinedMembers(.tMembers, pCube, pDimNo, pHierNo, pLevelNo) - quit:$$$ISERR(tSC) - set i = "" - for { - set i = $order(tMembers(i)) - quit:i="" - set tCount = tCount + 1 - } - quit:tCount - - // if none predefined, query domain - do ##class(%DeepSee.Utils).%GetDimensionFact(pCube, pDimNo, pHierNo, pLevelNo, .tFactName) - if (tFactName'="") { - set tIKMeasure = $g($$$DeepSeeMetaGLVN("cubes", tCube, "fact", "prop", tFactName, "iKnowMsr")) - if (tIKMeasure'="") { - set tDomainId = ##class(%iKnow.DeepSee.CubeUtils).GetDomainId(pCube, tIKMeasure) - if (tDomainId) { - &SQL(SELECT COUNT(*) INTO :tCount FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = :tDomainId) - if (SQLCODE=0) {} - elseif (SQLCODE=100) { set tCount = 0 } - else { set tSC = ##class(%SYSTEM.Error).FromSQLCode(SQLCODE).Status quit } - } - } - } - } catch (ex) { - set tSC = ex.AsStatus() - } - quit tCount -} - -Parameter CACHECOMPUTEDBITSET = "NEVER"; - -/// Resolve any special tokens or expression in a key value and return the result. -Method %ResolveKey(pSpec As %String, Output pRKey As %String) As %Status -{ - Set tSC = $$$OK - Set pRKey = $piece(pSpec,":",*) - Quit tSC -} - -} +Class Demo.SetAnalysis.ComputedDimension Extends %iKnow.DeepSee.Dimensions.Base +{ + +Method %ComputeIndexKey(pMemberKey As %String) As %String +{ + set:$f(pMemberKey,":") pMemberKey = $piece(pMemberKey,":",*) + Quit $ZCRC(pMemberKey,7) +} + +/// Method combining the functionality of %MemberSearch and +/// %OnGetComputedMembersFiltered to avoid having the same code twice.
+/// Returns entries of the form:
+/// pMembers(n) = $lb(id, name, key)
+/// Expects any predefined dimension members to supplied with pMemmbers upfront! +Method %OnGetComputedMembersInternal(ByRef pMembers, pSearchKey As %String = "", pRollupKey As %String = "", ByRef pRange As %String = "") As %Status [ Internal ] +{ + set tSC = $$$OK + try { + set tSQL = "SELECT ID, Name FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = ?" + set:pSearchKey'="" tSQL = tSQL_" AND Name LIKE '%"_pSearchKey_"%'" + set tStatement = ##class(%SQL.Statement).%New() + set tSC = tStatement.%Prepare(tSQL) + quit:$$$ISERR(tSC) + set tResult = tStatement.%Execute(..%ikDomainId) + while tResult.%Next() { + set pMembers($i(pMembers)) = $lb(tResult.%Get("Name"), tResult.%Get("Name"), tResult.%Get("Name")) + } + + } catch (ex) { + set tSC = ex.AsStatus() + } + quit tSC +} + +Method %FindComputedMemberByKey(pKey As %String, Output pFlag As %Boolean, Output pMemberName As %String, Output pMemberId As %String) As %Status +{ + set:$f(pKey,":") pKey = $piece(pKey,":",*) + set tSetObj = ##class(SetDefinition).NameIdxOpen(..%ikDomainId, pKey) + if $isobject(tSetObj) { + set pFlag=1, pMemberName=tSetObj.Name, pMemberId=pKey + } else { + set pFlag=0, pMemberName="", pMemberId="" + } + quit ..%ComputeBitset(pKey, .tIndexKey) +} + +/// Do the actual work of building the bitset. +Method %OnComputeBitset(pSpec As %String, pIndexKey As %String) As %Status +{ + set tSC = $$$OK + try { + set:$f(pSpec,":") pSpec = $piece(pSpec,":",*) + set tSetObj = ##class(SetDefinition).NameIdxOpen(..%ikDomainId, pSpec) + quit:tSetObj="" + + do tSetObj.GetFilter().ToBitstring(.tBits) + + kill $$$DeepSeeIndexGLVN(..%baseCube, ..%factNumber, pIndexKey) + merge $$$DeepSeeIndexGLVN(..%baseCube, ..%factNumber, pIndexKey) = tBits + + if (..%ikDomainType = "iKnow") { + set tIndexGlo = $name($$$DeepSeeIndexGLVN(..%baseCube, ..%factNumber, pIndexKey)) + set tSC = ##class(%iKnow.DeepSee.CubeUtils).TranslateIKnowBitstring(..%baseCube, ..%ikMeasure, tIndexGlo) + quit:$$$ISERR(tSC) + } + + } catch (ex) { + set tSC = ex.AsStatus() + } + quit tSC +} + +ClassMethod %Count(pCube As %String, pDimNo As %Integer, pHierNo As %Integer, pLevelNo As %Integer) As %Integer +{ + set tSC = $$$OK, tCount = 0 + try { + set tCube = $$$UPPER(pCube) + + // count number of pre-defined members + set tSC = ..%GetPredefinedMembers(.tMembers, pCube, pDimNo, pHierNo, pLevelNo) + quit:$$$ISERR(tSC) + set i = "" + for { + set i = $order(tMembers(i)) + quit:i="" + set tCount = tCount + 1 + } + quit:tCount + + // if none predefined, query domain + do ##class(%DeepSee.Utils).%GetDimensionFact(pCube, pDimNo, pHierNo, pLevelNo, .tFactName) + if (tFactName'="") { + set tIKMeasure = $g($$$DeepSeeMetaGLVN("cubes", tCube, "fact", "prop", tFactName, "iKnowMsr")) + if (tIKMeasure'="") { + set tDomainId = ##class(%iKnow.DeepSee.CubeUtils).GetDomainId(pCube, tIKMeasure) + if (tDomainId) { + &SQL(SELECT COUNT(*) INTO :tCount FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = :tDomainId) + if (SQLCODE=0) {} + elseif (SQLCODE=100) { set tCount = 0 } + else { set tSC = ##class(%SYSTEM.Error).FromSQLCode(SQLCODE).Status quit } + } + } + } + } catch (ex) { + set tSC = ex.AsStatus() + } + quit tCount +} + +Parameter CACHECOMPUTEDBITSET = "NEVER"; + +/// Resolve any special tokens or expression in a key value and return the result. +Method %ResolveKey(pSpec As %String, Output pRKey As %String) As %Status +{ + Set tSC = $$$OK + Set pRKey = $piece(pSpec,":",*) + Quit tSC +} + +} + diff --git a/src/cls/Demo/SetAnalysis/KnowledgePortal.cls b/src/cls/Demo/SetAnalysis/KnowledgePortal.cls index 4b573e1..143327c 100644 --- a/src/cls/Demo/SetAnalysis/KnowledgePortal.cls +++ b/src/cls/Demo/SetAnalysis/KnowledgePortal.cls @@ -1,61 +1,62 @@ -Class Demo.SetAnalysis.KnowledgePortal Extends %iKnow.UI.KnowledgePortal -{ - -/// Subclasses can override this method to supply custom filter types to be displayed -/// in the filter type dropdown in the following format: -/// pCustomFilterTypes(typeName) = typeLabel -ClassMethod GetCustomFilterTypes(Output pCustomFilterTypes) As %Status -{ - kill pCustomFilterTypes - set pCustomFilterTypes("set") = "Sets" - quit $$$OK -} - -/// Subclasses can override this method to draw the input fields specific to a custom -/// filter type added through GetCustomFilterTypes. -/// pSettings is the string capturing user input, as assembled by getCustomFilterSettings. -Method DrawCustomFilterInputs(pFilterType As %String, pSettings As %String) As %Status -{ - // sample code: - if (pFilterType = "set") { - write !,"" - quit $$$OK - } else { - quit $$$ERROR($$$GeneralError, "Unknown custom filter type: '"_pFilterType_"'") - } -} - -/// Subclasses can override this method to pick up the values of the input fields -/// specific to a custom filter type as draw in DrawCustomFilterIntputs -/// and concatenate them into a settings string. -ClientMethod getCustomFilterSettings(filterType) [ Language = javascript ] -{ - // sample code: - if (filterType=='set') { - return $('#selCustomFilterSetting').val(); - } - return ''; -} - -/// Subclasses can override this method to instantiate an actual %iKnow.Filters.Filter -/// object based on the supplied settings. -/// pSettings is the string capturing user input, as assembled by getCustomFilterSettings. -Method CreateCustomFilter(pFilterType As %String, pSettings As %String) As %iKnow.Filters.Filter -{ - // sample code: - if (pFilterType="set") { - set tSetDef = ##class(Demo.SetAnalysis.SetDefinition).%OpenId(pSettings) - quit:tSetDef="" "" - quit tSetDef.GetSDFilter() - } - quit "" -} - -} +Class Demo.SetAnalysis.KnowledgePortal Extends %iKnow.UI.KnowledgePortal +{ + +/// Subclasses can override this method to supply custom filter types to be displayed +/// in the filter type dropdown in the following format: +/// pCustomFilterTypes(typeName) = typeLabel +ClassMethod GetCustomFilterTypes(Output pCustomFilterTypes) As %Status +{ + kill pCustomFilterTypes + set pCustomFilterTypes("set") = "Sets" + quit $$$OK +} + +/// Subclasses can override this method to draw the input fields specific to a custom +/// filter type added through GetCustomFilterTypes. +/// pSettings is the string capturing user input, as assembled by getCustomFilterSettings. +Method DrawCustomFilterInputs(pFilterType As %String, pSettings As %String) As %Status +{ + // sample code: + if (pFilterType = "set") { + write !,"" + quit $$$OK + } else { + quit $$$ERROR($$$GeneralError, "Unknown custom filter type: '"_pFilterType_"'") + } +} + +/// Subclasses can override this method to pick up the values of the input fields +/// specific to a custom filter type as draw in DrawCustomFilterIntputs +/// and concatenate them into a settings string. +ClientMethod getCustomFilterSettings(filterType) [ Language = javascript ] +{ + // sample code: + if (filterType=='set') { + return $('#selCustomFilterSetting').val(); + } + return ''; +} + +/// Subclasses can override this method to instantiate an actual %iKnow.Filters.Filter +/// object based on the supplied settings. +/// pSettings is the string capturing user input, as assembled by getCustomFilterSettings. +Method CreateCustomFilter(pFilterType As %String, pSettings As %String) As %iKnow.Filters.Filter +{ + // sample code: + if (pFilterType="set") { + set tSetDef = ##class(Demo.SetAnalysis.SetDefinition).%OpenId(pSettings) + quit:tSetDef="" "" + quit tSetDef.GetSDFilter() + } + quit "" +} + +} + diff --git a/src/cls/Demo/SetAnalysis/RestHandler.cls b/src/cls/Demo/SetAnalysis/RestHandler.cls index 16eb51a..14f0db2 100644 --- a/src/cls/Demo/SetAnalysis/RestHandler.cls +++ b/src/cls/Demo/SetAnalysis/RestHandler.cls @@ -1,899 +1,900 @@ -Include %IKPublic - -IncludeGenerator %IKPublic - -Class Demo.SetAnalysis.RestHandler Extends %CSP.REST -{ - -Parameter CONTENTTYPE = "application/json"; - -Parameter IKPAGESIZE As INTEGER = 200; - -/// As the app only shows spread, this filter mode will do all we need with less work than -/// the classic $$$FILTERALLANDSORT -Parameter IKPFILTERMODE As INTEGER = {$$$FILTERALLANDSORT}; - -Parameter JSONFORMATPARAMS As STRING = "aelotwu"; - -XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ] -{ - - - - - - - - - - - - - - - - - - - - - - - - - -} - -/// Retrieves all sources (including full text and metadata) in the domain and prints them as JSON -ClassMethod GetSources(pDomainId As %Integer) As %Status -{ - set tSC = $$$OK - try { - set tSC = ..GetSourcesInternal(pDomainId) - quit:$$$ISERR(tSC) - } catch (ex) { - set tSC = ex.AsStatus() - } - quit ..ErrorHandler(tSC) -} - -ClassMethod GetFilter(pDomainId As %Integer, pFilterSpec As %String = "") As %iKnow.Filters.Filter [ Private ] -{ - set:pFilterSpec="" pFilterSpec = %request.Content.filter - quit:(pFilterSpec="") "" - set tSetDef = ##class(Demo.SetAnalysis.SetDefinition).NameIdxOpen(pDomainId, pFilterSpec) - quit:'$isobject(tSetDef) "" - quit tSetDef.GetFilter() -} - -/// Retrieves all sentences (including full text) in the domain containing pEntity and prints them as JSON -ClassMethod GetSentences(pDomainId As %Integer, pRequest As %String, pIncludeSentimentFlags As %Boolean = 1) As %Status -{ - set tSC = $$$OK - try { - set:$data(%response) %response.ContentType="application/json" - - if (%request.Content.type = "entity") { - set tEntityId = ##class(%iKnow.Queries.EntityAPI).GetId(pDomainId, %request.Content.value) - set:'tEntityId tEntityId = ##class(%iKnow.Queries.EntityAPI).GetId(pDomainId, $zcvt(%request.Content.value,"I","URL")) - set tHighlight("ENTITY", tEntityId) = "" - set tSC = ##class(%iKnow.Queries.SentenceAPI).GetByEntities(.tSentences, pDomainId, %request.Content.value, ..GetFilter(pDomainId, %request.Content.filter), 1, ..#IKPAGESIZE) - quit:$$$ISERR(tSC) - } else { - set tCRCId = ##class(%iKnow.Queries.CrcAPI).GetId(pDomainId, $piece(%request.Content.value," ~ ",1), $piece(%request.Content.value," ~ ",2), $piece(%request.Content.value," ~ ",3)) - set tHighlight("CRC", tCRCId) = "" - set tSC = ##class(%iKnow.Queries.SentenceAPI).GetByCrcIds(.tSentences, pDomainId, tCRCId, ..GetFilter(pDomainId, %request.Content.filter), 1, ..#IKPAGESIZE) - quit:$$$ISERR(tSC) - } - - set tJSON = ##class(%ZEN.proxyObject).%New() - set tJSON.Sentences = ##class(%ListOfObjects).%New() - set i = "" - for { - set i = $order(tSentences(i), 1, tSentData) - quit:i="" - set tSentId = $lg(tSentData,3) - set tProxy = ##class(%ZEN.proxyObject).%New() - set tProxy.SourceId = $lg(tSentData,1) - set tProxy.ExternalId = $lg(tSentData,2) - set tProxy.SentenceId = $lg(tSentData,3) - set tProxy.Text = ..GetHighlightedSentence(pDomainId, tProxy.SentenceId, .tHighlight, .tSC) - quit:$$$ISERR(tSC) - - if pIncludeSentimentFlags && (%request.Content.type = "entity") { - set tSC = ##class(%iKnow.Queries.SentenceAPI).GetParts(.tParts, pDomainId, tProxy.SentenceId) - quit:$$$ISERR(tSC) - set j = "" - for { - set j = $order(tParts(j),1,tPartData) - quit:j="" - continue:$lg(tPartData,2)'=tEntityId - set:##class(%iKnow.Queries.EntityAPI).IsAttributed(pDomainId, $lg(tPartData,1), $$$IKATTSENPOSITIVE) tProxy.HasPositive = 1 - set:##class(%iKnow.Queries.EntityAPI).IsAttributed(pDomainId, $lg(tPartData,1), $$$IKATTSENNEGATIVE) tProxy.HasNegative = 1 - } - } - - do tJSON.Sentences.Insert(tProxy) - } - quit:$$$ISERR(tSC) - - do tJSON.%ToJSON(,..#JSONFORMATPARAMS) - - } catch (ex) { - set tSC=ex.AsStatus() - } - quit ..ErrorHandler(tSC) -} - -/// Retrieves the list of sources in pSetId and prints them to JSON. -ClassMethod GetSourcesBySet(pDomainId As %Integer, pSetId As %Integer) As %Status -{ - set tSC = $$$OK - try { - set tSet = ##class(SetDefinition).%OpenId(pSetId) - - // retrieve entities of both sets to highlight - set tEntities = tSet.GetEntities() - for i = 1:1:tEntities.Count() { - set tEntity = tEntities.GetAt(i) - continue:tEntity="" - set tHighlight("ENTITY", tEntity) = "" - } - set tCRCs = tSet.GetCRCs() - for i = 1:1:tCRCs.Count() { - set tCRC = tCRCs.GetAt(i) - continue:tCRC="" - set tCRCId = ##class(%iKnow.Queries.CrcAPI).GetId(pDomainId, $piece(tCRC," ~ ",1), $piece(tCRC," ~ ",2), $piece(tCRC," ~ ",3)) - set tHighlight("CRC", tCRCId) = "" - } - - set tSC = ..GetSourcesInternal(pDomainId, tSet.GetFilter(),, .tHighlight, 0) - quit:$$$ISERR(tSC) - - } catch (ex) { - set tSC = ex.AsStatus() - } - quit ..ErrorHandler(tSC) -} - -/// Retrieves the list of sources part of both pSetId1 and pSetId2 and prints them to JSON. -ClassMethod GetSourcesBySetOverlap(pDomainId As %Integer, pSetId1 As %Integer, pSetId2 As %Integer) As %Status -{ - set tSC = $$$OK - try { - set tSet1 = ##class(SetDefinition).%OpenId(pSetId1) - set tSet2 = ##class(SetDefinition).%OpenId(pSetId2) - - set tFilter = ##class(%iKnow.Filters.GroupFilter).%New(pDomainId, $$$GROUPFILTERAND) - do tFilter.AddSubFilter(tSet1.GetFilter()) - do tFilter.AddSubFilter(tSet2.GetFilter()) - - // retrieve entities of both sets to highlight - set tEntities1 = tSet1.GetEntities() - for i = 1:1:tEntities1.Count() { - set tEntity = tEntities1.GetAt(i) - continue:tEntity="" - set tHighlight("ENTITY", tEntity) = "" - } - set tCRCs1 = tSet1.GetCRCs() - for i = 1:1:tCRCs1.Count() { - set tCRC = tCRCs1.GetAt(i) - continue:tCRC="" - set tCRCId = ##class(%iKnow.Queries.CrcAPI).GetId(pDomainId, $piece(tCRC," ~ ",1), $piece(tCRC," ~ ",2), $piece(tCRC," ~ ",3)) - set tHighlight("CRC", tCRCId) = "" - } - - set tEntities2 = tSet2.GetEntities() - for i = 1:1:tEntities2.Count() { - set tEntity = tEntities2.GetAt(i) - continue:tEntity="" - set tHighlight("ENTITY", tEntity) = "" - } - set tCRCs2 = tSet2.GetCRCs() - for i = 1:1:tCRCs2.Count() { - set tCRC = tCRCs2.GetAt(i) - continue:tCRC="" - set tCRCId = ##class(%iKnow.Queries.CrcAPI).GetId(pDomainId, $piece(tCRC," ~ ",1), $piece(tCRC," ~ ",2), $piece(tCRC," ~ ",3)) - set tHighlight("CRC", tCRCId) = "" - } - - set tSC = ..GetSourcesInternal(pDomainId, tFilter,, .tHighlight, 0) - quit:$$$ISERR(tSC) - - } catch (ex) { - set tSC = ex.AsStatus() - } - quit ..ErrorHandler(tSC) -} - -/// Utility method to print a list of sources to JSON -ClassMethod GetSourcesInternal(pDomainId As %Integer, pFilter As %iKnow.Filters.Filter = "", pFilterByEntity As %String = "", ByRef pHighlight, pGetMetadata As %Boolean = 1) As %Status [ Private ] -{ - set tSC = $$$OK - try { - set:$data(%response) %response.ContentType="application/json" - - // fetch SetDefinition objects for set membership metadata - set tSets = 0 - if (pGetMetadata) { - set tSQL = "SELECT ID FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = "_pDomainId - set tResult = ##class(%SQL.Statement).%ExecDirect(,tSQL) - while tResult.%Next() { - set tSets($i(tSets)) = ##class(SetDefinition).%OpenId(tResult.%Get("ID")) - } - kill tResult - } - - set tJSON = ##class(%ZEN.proxyObject).%New() - set tJSON.Sources = ##class(%ListOfObjects).%New() - set tSC = ##class(%iKnow.Queries.SourceAPI).GetByDomain(.tResult, pDomainId, 1, ..#IKPAGESIZE, pFilter) - quit:$$$ISERR(tSC) - set i = "" - for { - set i = $order(tResult(i), 1, tData) - quit:i="" - - set tSrcId = $lg(tData,1) - set tProxy = ##class(%ZEN.proxyObject).%New() - set tProxy.SourceId = tSrcId - - // add fulltext - set tProxy.FullText = ..GetHighlightedSource(pDomainId, tSrcId, pFilterByEntity,, .pHighlight, .tSC) - quit:$$$ISERR(tSC) - - // add metadata - if pGetMetadata { - set tSC = ##class(%iKnow.Queries.MetadataAPI).GetValuesById(.tMetadata, pDomainId, tSrcId) - quit:$$$ISERR(tSC) - set j = "" - for { - set j = $order(tMetadata(j),1,tMD) - quit:j="" - set tFieldName = $li(tMD,2) - continue:tFieldName="DateIndexed" - set $property(tProxy,tFieldName) = $lg(tMD,3) - } - - // get sets for source - set tProxy.Sets = ##class(%ListOfObjects).%New() - for j = 1:1:tSets { - if $isobject(tSets(j).GetFilter()) && tSets(j).GetFilter().IsFiltered(tSrcId) { - do tProxy.Sets.Insert(tSets(j)) - } - } - } - - do tJSON.Sources.Insert(tProxy) - } - - do tJSON.%ToJSON(,..#JSONFORMATPARAMS) - } catch (ex) { - set tSC = ex.AsStatus() - } - quit ..ErrorHandler(tSC) -} - -ClassMethod GetSource(pDomainId As %Integer, pSourceId As %Integer) As %Status -{ - set tSC = $$$OK - try { - set:$data(%response) %response.ContentType="application/json" - - set tJSON = ##class(%ZEN.proxyObject).%New() - set tJSON.SourceId = pSourceId - set tJSON.Text = ..GetHighlightedSource(pDomainId, pSourceId,, 9999,,.tSC) - quit:$$$ISERR(tSC) - - set tJSON.Metadata = ##class(%ZEN.proxyObject).%New() - set tSC = ##class(%iKnow.Queries.MetadataAPI).GetValuesById(.tMetadata, pDomainId, pSourceId) - quit:$$$ISERR(tSC) - set j = "" - for { - set j = $order(tMetadata(j),1,tMD) - quit:j="" - set tFieldName = $li(tMD,2) - continue:tFieldName="DateIndexed" - set $property(tJSON.Metadata,tFieldName) = $lg(tMD,3) - } - - // get sets for source - set tSQL = "SELECT ID FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = "_pDomainId - set tResult = ##class(%SQL.Statement).%ExecDirect(,tSQL) - while tResult.%Next() { - set tSets($i(tSets)) = ##class(SetDefinition).%OpenId(tResult.%Get("ID")) - } - kill tResult - set tJSON.Sets = ##class(%ListOfObjects).%New() - for j = 1:1:tSets { - if tSets(j).GetFilter().IsFiltered(pSourceId) { - do tJSON.Sets.Insert(tSets(j)) - } - } - - do tJSON.%ToJSON(,..#JSONFORMATPARAMS) - } catch (ex) { - set tSC = ex.AsStatus() - } - quit ..ErrorHandler(tSC) -} - -/// Retrieves a highlighted summary of the text in source pSourceId, optionally filtered to the -/// sentences containing pFilterByEntity. At most pMaxSentences will be returned. -/// Any markup in pHighlight is appended with default highlighting of negations -ClassMethod GetHighlightedSource(pDomainId As %Integer, pSourceId As %Integer, pFilterByEntity As %String = "", pMaxSentences As %Integer = 5, ByRef pHighlight, Output pSC As %Status = {$$$OK}) As %String -{ - set pSC = $$$OK, tString = "" - try { - - // first select by entities - if (pFilterByEntity'="") { - set pHighlight("ENTITY", pFilterByEntity) = "" - set pSC = ##class(%iKnow.Queries.SentenceAPI).GetByEntities(.tSentences, pDomainId, pFilterByEntity, $lb(pSourceId), 0) - quit:$$$ISERR(pSC) - } elseif $d(pHighlight("ENTITY")) { - set tEntity = "", tEntityList="" - for { - set tEntity = $order(pHighlight("ENTITY",tEntity)) - quit:tEntity="" - set tEntityList = tEntityList _ $lb(tEntity) - } - set pSC = ##class(%iKnow.Queries.SentenceAPI).GetByEntities(.tSentences, pDomainId, tEntityList, $lb(pSourceId), 0) - quit:$$$ISERR(pSC) - } - set i = "", tSentIDs = "" - for { - set i = $order(tSentences(i),1,tSentData) - quit:i="" - set tSentIDs = tSentIDs _ $li(tSentData,3,3) - } - - // now fetch the sentences of this source... - // first selected by whether they are in tSentIDs, then based on summary relevance - // and back in natural order - set tSQL = "SELECT SentenceId, SummaryRelevance FROM %iKnow_Objects.Sentence WHERE DomainId = ? AND SourceId = ?" - set tSQL = "SELECT TOP ? * FROM ("_tSQL_") ORDER BY CASE WHEN (SentenceId %INLIST ?) THEN 1 ELSE 0 END DESC, SummaryRelevance DESC" - set tSQL = "SELECT * FROM ("_tSQL_") ORDER BY SentenceId ASC" - set tStatement = ##class(%SQL.Statement).%New() - set pSC = tStatement.%Prepare(tSQL) - quit:$$$ISERR(pSC) - set tResult = tStatement.%Execute(pMaxSentences, pDomainId, pSourceId, tSentIDs) - - - set tSource = ##class(%iKnow.Objects.Source).PKINDEXOpen(pDomainId, pSourceId) - set tPrevSentId = tSource.FirstSentenceId-1, tSentId="" - while tResult.%Next() { - set tSentId = tResult.%Get("SentenceId") - - set tString = tString _ $s((tPrevSentId'=(tSentId-1)):" ... ", 1:" ") - set tPrevSentId = tSentId - - set tString = tString _ ..GetHighlightedSentence(pDomainId, tSentId, .pHighlight, .pSC) - quit:$$$ISERR(pSC) - } - if tSentId'=(tSource.FirstSentenceId+tSource.SentenceCount-1) { - set tString = tString _ " ..." - } - - } catch (ex) { - set pSC = ex.AsStatus() - } - quit tString -} - -ClassMethod GetHighlightedSentence(pDomainId As %Integer, pSentenceId As %Integer, ByRef pHighlight, Output pSC As %Status) As %String -{ - set pSC = $$$OK, tSentence = "" - try { - // default highlighting - set tHighlight("ATTRIBUTE", $$$IKATTSENPOSITIVE) = "" - set tHighlight("ATTRIBUTE", $$$IKATTSENNEGATIVE) = "" - 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) -} - -} +Include %IKPublic + +IncludeGenerator %IKPublic + +Class Demo.SetAnalysis.RestHandler Extends %CSP.REST +{ + +Parameter CONTENTTYPE = "application/json"; + +Parameter IKPAGESIZE As INTEGER = 200; + +/// As the app only shows spread, this filter mode will do all we need with less work than +/// the classic $$$FILTERALLANDSORT +Parameter IKPFILTERMODE As INTEGER = {$$$FILTERALLANDSORT}; + +Parameter JSONFORMATPARAMS As STRING = "aelotwu"; + +XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ] +{ + + + + + + + + + + + + + + + + + + + + + + + + + +} + +/// Retrieves all sources (including full text and metadata) in the domain and prints them as JSON +ClassMethod GetSources(pDomainId As %Integer) As %Status +{ + set tSC = $$$OK + try { + set tSC = ..GetSourcesInternal(pDomainId) + quit:$$$ISERR(tSC) + } catch (ex) { + set tSC = ex.AsStatus() + } + quit ..ErrorHandler(tSC) +} + +ClassMethod GetFilter(pDomainId As %Integer, pFilterSpec As %String = "") As %iKnow.Filters.Filter [ Private ] +{ + set:pFilterSpec="" pFilterSpec = %request.Content.filter + quit:(pFilterSpec="") "" + set tSetDef = ##class(Demo.SetAnalysis.SetDefinition).NameIdxOpen(pDomainId, pFilterSpec) + quit:'$isobject(tSetDef) "" + quit tSetDef.GetFilter() +} + +/// Retrieves all sentences (including full text) in the domain containing pEntity and prints them as JSON +ClassMethod GetSentences(pDomainId As %Integer, pRequest As %String, pIncludeSentimentFlags As %Boolean = 1) As %Status +{ + set tSC = $$$OK + try { + set:$data(%response) %response.ContentType="application/json" + + if (%request.Content.type = "entity") { + set tEntityId = ##class(%iKnow.Queries.EntityAPI).GetId(pDomainId, %request.Content.value) + set:'tEntityId tEntityId = ##class(%iKnow.Queries.EntityAPI).GetId(pDomainId, $zcvt(%request.Content.value,"I","URL")) + set tHighlight("ENTITY", tEntityId) = "" + set tSC = ##class(%iKnow.Queries.SentenceAPI).GetByEntities(.tSentences, pDomainId, %request.Content.value, ..GetFilter(pDomainId, %request.Content.filter), 1, ..#IKPAGESIZE) + quit:$$$ISERR(tSC) + } else { + set tCRCId = ##class(%iKnow.Queries.CrcAPI).GetId(pDomainId, $piece(%request.Content.value," ~ ",1), $piece(%request.Content.value," ~ ",2), $piece(%request.Content.value," ~ ",3)) + set tHighlight("CRC", tCRCId) = "" + set tSC = ##class(%iKnow.Queries.SentenceAPI).GetByCrcIds(.tSentences, pDomainId, tCRCId, ..GetFilter(pDomainId, %request.Content.filter), 1, ..#IKPAGESIZE) + quit:$$$ISERR(tSC) + } + + set tJSON = ##class(%ZEN.proxyObject).%New() + set tJSON.Sentences = ##class(%ListOfObjects).%New() + set i = "" + for { + set i = $order(tSentences(i), 1, tSentData) + quit:i="" + set tSentId = $lg(tSentData,3) + set tProxy = ##class(%ZEN.proxyObject).%New() + set tProxy.SourceId = $lg(tSentData,1) + set tProxy.ExternalId = $lg(tSentData,2) + set tProxy.SentenceId = $lg(tSentData,3) + set tProxy.Text = ..GetHighlightedSentence(pDomainId, tProxy.SentenceId, .tHighlight, .tSC) + quit:$$$ISERR(tSC) + + if pIncludeSentimentFlags && (%request.Content.type = "entity") { + set tSC = ##class(%iKnow.Queries.SentenceAPI).GetParts(.tParts, pDomainId, tProxy.SentenceId) + quit:$$$ISERR(tSC) + set j = "" + for { + set j = $order(tParts(j),1,tPartData) + quit:j="" + continue:$lg(tPartData,2)'=tEntityId + set:##class(%iKnow.Queries.EntityAPI).IsAttributed(pDomainId, $lg(tPartData,1), $$$IKATTSENPOSITIVE) tProxy.HasPositive = 1 + set:##class(%iKnow.Queries.EntityAPI).IsAttributed(pDomainId, $lg(tPartData,1), $$$IKATTSENNEGATIVE) tProxy.HasNegative = 1 + } + } + + do tJSON.Sentences.Insert(tProxy) + } + quit:$$$ISERR(tSC) + + do tJSON.%ToJSON(,..#JSONFORMATPARAMS) + + } catch (ex) { + set tSC=ex.AsStatus() + } + quit ..ErrorHandler(tSC) +} + +/// Retrieves the list of sources in pSetId and prints them to JSON. +ClassMethod GetSourcesBySet(pDomainId As %Integer, pSetId As %Integer) As %Status +{ + set tSC = $$$OK + try { + set tSet = ##class(SetDefinition).%OpenId(pSetId) + + // retrieve entities of both sets to highlight + set tEntities = tSet.GetEntities() + for i = 1:1:tEntities.Count() { + set tEntity = tEntities.GetAt(i) + continue:tEntity="" + set tHighlight("ENTITY", tEntity) = "" + } + set tCRCs = tSet.GetCRCs() + for i = 1:1:tCRCs.Count() { + set tCRC = tCRCs.GetAt(i) + continue:tCRC="" + set tCRCId = ##class(%iKnow.Queries.CrcAPI).GetId(pDomainId, $piece(tCRC," ~ ",1), $piece(tCRC," ~ ",2), $piece(tCRC," ~ ",3)) + set tHighlight("CRC", tCRCId) = "" + } + + set tSC = ..GetSourcesInternal(pDomainId, tSet.GetFilter(),, .tHighlight, 0) + quit:$$$ISERR(tSC) + + } catch (ex) { + set tSC = ex.AsStatus() + } + quit ..ErrorHandler(tSC) +} + +/// Retrieves the list of sources part of both pSetId1 and pSetId2 and prints them to JSON. +ClassMethod GetSourcesBySetOverlap(pDomainId As %Integer, pSetId1 As %Integer, pSetId2 As %Integer) As %Status +{ + set tSC = $$$OK + try { + set tSet1 = ##class(SetDefinition).%OpenId(pSetId1) + set tSet2 = ##class(SetDefinition).%OpenId(pSetId2) + + set tFilter = ##class(%iKnow.Filters.GroupFilter).%New(pDomainId, $$$GROUPFILTERAND) + do tFilter.AddSubFilter(tSet1.GetFilter()) + do tFilter.AddSubFilter(tSet2.GetFilter()) + + // retrieve entities of both sets to highlight + set tEntities1 = tSet1.GetEntities() + for i = 1:1:tEntities1.Count() { + set tEntity = tEntities1.GetAt(i) + continue:tEntity="" + set tHighlight("ENTITY", tEntity) = "" + } + set tCRCs1 = tSet1.GetCRCs() + for i = 1:1:tCRCs1.Count() { + set tCRC = tCRCs1.GetAt(i) + continue:tCRC="" + set tCRCId = ##class(%iKnow.Queries.CrcAPI).GetId(pDomainId, $piece(tCRC," ~ ",1), $piece(tCRC," ~ ",2), $piece(tCRC," ~ ",3)) + set tHighlight("CRC", tCRCId) = "" + } + + set tEntities2 = tSet2.GetEntities() + for i = 1:1:tEntities2.Count() { + set tEntity = tEntities2.GetAt(i) + continue:tEntity="" + set tHighlight("ENTITY", tEntity) = "" + } + set tCRCs2 = tSet2.GetCRCs() + for i = 1:1:tCRCs2.Count() { + set tCRC = tCRCs2.GetAt(i) + continue:tCRC="" + set tCRCId = ##class(%iKnow.Queries.CrcAPI).GetId(pDomainId, $piece(tCRC," ~ ",1), $piece(tCRC," ~ ",2), $piece(tCRC," ~ ",3)) + set tHighlight("CRC", tCRCId) = "" + } + + set tSC = ..GetSourcesInternal(pDomainId, tFilter,, .tHighlight, 0) + quit:$$$ISERR(tSC) + + } catch (ex) { + set tSC = ex.AsStatus() + } + quit ..ErrorHandler(tSC) +} + +/// Utility method to print a list of sources to JSON +ClassMethod GetSourcesInternal(pDomainId As %Integer, pFilter As %iKnow.Filters.Filter = "", pFilterByEntity As %String = "", ByRef pHighlight, pGetMetadata As %Boolean = 1) As %Status [ Private ] +{ + set tSC = $$$OK + try { + set:$data(%response) %response.ContentType="application/json" + + // fetch SetDefinition objects for set membership metadata + set tSets = 0 + if (pGetMetadata) { + set tSQL = "SELECT ID FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = "_pDomainId + set tResult = ##class(%SQL.Statement).%ExecDirect(,tSQL) + while tResult.%Next() { + set tSets($i(tSets)) = ##class(SetDefinition).%OpenId(tResult.%Get("ID")) + } + kill tResult + } + + set tJSON = ##class(%ZEN.proxyObject).%New() + set tJSON.Sources = ##class(%ListOfObjects).%New() + set tSC = ##class(%iKnow.Queries.SourceAPI).GetByDomain(.tResult, pDomainId, 1, ..#IKPAGESIZE, pFilter) + quit:$$$ISERR(tSC) + set i = "" + for { + set i = $order(tResult(i), 1, tData) + quit:i="" + + set tSrcId = $lg(tData,1) + set tProxy = ##class(%ZEN.proxyObject).%New() + set tProxy.SourceId = tSrcId + + // add fulltext + set tProxy.FullText = ..GetHighlightedSource(pDomainId, tSrcId, pFilterByEntity,, .pHighlight, .tSC) + quit:$$$ISERR(tSC) + + // add metadata + if pGetMetadata { + set tSC = ##class(%iKnow.Queries.MetadataAPI).GetValuesById(.tMetadata, pDomainId, tSrcId) + quit:$$$ISERR(tSC) + set j = "" + for { + set j = $order(tMetadata(j),1,tMD) + quit:j="" + set tFieldName = $li(tMD,2) + continue:tFieldName="DateIndexed" + set $property(tProxy,tFieldName) = $lg(tMD,3) + } + + // get sets for source + set tProxy.Sets = ##class(%ListOfObjects).%New() + for j = 1:1:tSets { + if $isobject(tSets(j).GetFilter()) && tSets(j).GetFilter().IsFiltered(tSrcId) { + do tProxy.Sets.Insert(tSets(j)) + } + } + } + + do tJSON.Sources.Insert(tProxy) + } + + do tJSON.%ToJSON(,..#JSONFORMATPARAMS) + } catch (ex) { + set tSC = ex.AsStatus() + } + quit ..ErrorHandler(tSC) +} + +ClassMethod GetSource(pDomainId As %Integer, pSourceId As %Integer) As %Status +{ + set tSC = $$$OK + try { + set:$data(%response) %response.ContentType="application/json" + + set tJSON = ##class(%ZEN.proxyObject).%New() + set tJSON.SourceId = pSourceId + set tJSON.Text = ..GetHighlightedSource(pDomainId, pSourceId,, 9999,,.tSC) + quit:$$$ISERR(tSC) + + set tJSON.Metadata = ##class(%ZEN.proxyObject).%New() + set tSC = ##class(%iKnow.Queries.MetadataAPI).GetValuesById(.tMetadata, pDomainId, pSourceId) + quit:$$$ISERR(tSC) + set j = "" + for { + set j = $order(tMetadata(j),1,tMD) + quit:j="" + set tFieldName = $li(tMD,2) + continue:tFieldName="DateIndexed" + set $property(tJSON.Metadata,tFieldName) = $lg(tMD,3) + } + + // get sets for source + set tSQL = "SELECT ID FROM Demo_SetAnalysis.SetDefinition WHERE DomainId = "_pDomainId + set tResult = ##class(%SQL.Statement).%ExecDirect(,tSQL) + while tResult.%Next() { + set tSets($i(tSets)) = ##class(SetDefinition).%OpenId(tResult.%Get("ID")) + } + kill tResult + set tJSON.Sets = ##class(%ListOfObjects).%New() + for j = 1:1:tSets { + if tSets(j).GetFilter().IsFiltered(pSourceId) { + do tJSON.Sets.Insert(tSets(j)) + } + } + + do tJSON.%ToJSON(,..#JSONFORMATPARAMS) + } catch (ex) { + set tSC = ex.AsStatus() + } + quit ..ErrorHandler(tSC) +} + +/// Retrieves a highlighted summary of the text in source pSourceId, optionally filtered to the +/// sentences containing pFilterByEntity. At most pMaxSentences will be returned. +/// Any markup in pHighlight is appended with default highlighting of negations +ClassMethod GetHighlightedSource(pDomainId As %Integer, pSourceId As %Integer, pFilterByEntity As %String = "", pMaxSentences As %Integer = 5, ByRef pHighlight, Output pSC As %Status = {$$$OK}) As %String +{ + set pSC = $$$OK, tString = "" + try { + + // first select by entities + if (pFilterByEntity'="") { + set pHighlight("ENTITY", pFilterByEntity) = "" + set pSC = ##class(%iKnow.Queries.SentenceAPI).GetByEntities(.tSentences, pDomainId, pFilterByEntity, $lb(pSourceId), 0) + quit:$$$ISERR(pSC) + } elseif $d(pHighlight("ENTITY")) { + set tEntity = "", tEntityList="" + for { + set tEntity = $order(pHighlight("ENTITY",tEntity)) + quit:tEntity="" + set tEntityList = tEntityList _ $lb(tEntity) + } + set pSC = ##class(%iKnow.Queries.SentenceAPI).GetByEntities(.tSentences, pDomainId, tEntityList, $lb(pSourceId), 0) + quit:$$$ISERR(pSC) + } + set i = "", tSentIDs = "" + for { + set i = $order(tSentences(i),1,tSentData) + quit:i="" + set tSentIDs = tSentIDs _ $li(tSentData,3,3) + } + + // now fetch the sentences of this source... + // first selected by whether they are in tSentIDs, then based on summary relevance + // and back in natural order + set tSQL = "SELECT SentenceId, SummaryRelevance FROM %iKnow_Objects.Sentence WHERE DomainId = ? AND SourceId = ?" + set tSQL = "SELECT TOP ? * FROM ("_tSQL_") ORDER BY CASE WHEN (SentenceId %INLIST ?) THEN 1 ELSE 0 END DESC, SummaryRelevance DESC" + set tSQL = "SELECT * FROM ("_tSQL_") ORDER BY SentenceId ASC" + set tStatement = ##class(%SQL.Statement).%New() + set pSC = tStatement.%Prepare(tSQL) + quit:$$$ISERR(pSC) + set tResult = tStatement.%Execute(pMaxSentences, pDomainId, pSourceId, tSentIDs) + + + set tSource = ##class(%iKnow.Objects.Source).PKINDEXOpen(pDomainId, pSourceId) + set tPrevSentId = tSource.FirstSentenceId-1, tSentId="" + while tResult.%Next() { + set tSentId = tResult.%Get("SentenceId") + + set tString = tString _ $s((tPrevSentId'=(tSentId-1)):" ... ", 1:" ") + set tPrevSentId = tSentId + + set tString = tString _ ..GetHighlightedSentence(pDomainId, tSentId, .pHighlight, .pSC) + quit:$$$ISERR(pSC) + } + if tSentId'=(tSource.FirstSentenceId+tSource.SentenceCount-1) { + set tString = tString _ " ..." + } + + } catch (ex) { + set pSC = ex.AsStatus() + } + quit tString +} + +ClassMethod GetHighlightedSentence(pDomainId As %Integer, pSentenceId As %Integer, ByRef pHighlight, Output pSC As %Status) As %String +{ + set pSC = $$$OK, tSentence = "" + try { + // default highlighting + set tHighlight("ATTRIBUTE", $$$IKATTSENPOSITIVE) = "" + set tHighlight("ATTRIBUTE", $$$IKATTSENNEGATIVE) = "" + 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 +} + +} + From fbbbb8be0b149be5ffe68727fd0d91465b0d0bef Mon Sep 17 00:00:00 2001 From: SergeyMi37 Date: Fri, 2 Sep 2022 17:24:06 +0300 Subject: [PATCH 2/2] added invoke to module --- module.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/module.xml b/module.xml index 85d2e87..27ac0e3 100644 --- a/module.xml +++ b/module.xml @@ -3,10 +3,13 @@ isc-iknow-setanalysis - 1.0.0 + 1.0.1 About Set Analysis Demo app for InterSystems' iKnow technology module src + + /isc-iknow-setanalysis +