├── sc-list.txt ├── .DS_Store ├── docker-compose.yml ├── module.xml ├── irissession.sh ├── Dockerfile ├── LICENSE ├── Installer.cls ├── README.md └── src └── cls └── IDP └── DV.cls /sc-list.txt: -------------------------------------------------------------------------------- 1 | CDV.pkg 2 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intersystems-community/CDV/master/.DS_Store -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.6' 2 | services: 3 | iris: 4 | build: 5 | context: . 6 | dockerfile: Dockerfile 7 | restart: always 8 | ports: 9 | - 1972 10 | - 51773 11 | - 52773 12 | - 53773 13 | volumes: 14 | - ~/iris.key:/usr/irissys/mgr/iris.key 15 | - ./:/irisdev/app 16 | -------------------------------------------------------------------------------- /module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | idp-dv 6 | 1.3.1 7 | Class data verifier. Utility validates Intersystems IRIS classes properties data according to the properties' types. 8 | module 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /irissession.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | iris start $ISC_PACKAGE_INSTANCENAME quietly 4 | 5 | cat << EOF | iris session $ISC_PACKAGE_INSTANCENAME -U %SYS 6 | do ##class(%SYSTEM.Process).CurrentDirectory("$PWD") 7 | $@ 8 | if '\$Get(sc) do ##class(%SYSTEM.Process).Terminate(, 1) 9 | zn "%SYS" 10 | do ##class(SYS.Container).QuiesceForBundling() 11 | Do ##class(Security.Users).UnExpireUserPasswords("*") 12 | halt 13 | EOF 14 | 15 | exit=$? 16 | 17 | iris stop $ISC_PACKAGE_INSTANCENAME quietly 18 | 19 | exit $exit -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG IMAGE=store/intersystems/irishealth:2019.3.0.308.0-community 2 | ARG IMAGE=store/intersystems/iris-community:2019.3.0.309.0 3 | ARG IMAGE=store/intersystems/iris-community:2019.4.0.379.0 4 | ARG IMAGE=store/intersystems/iris-community:2020.1.0.199.0 5 | # ARG IMAGE=intersystemsdc/iris-community:2019.4.0.383.0-zpm 6 | ARG IMAGE=intersystemsdc/iris-community:2020.4.0.524.0-zpm 7 | ARG IMAGE=intersystemsdc/iris-community:latest 8 | FROM $IMAGE 9 | 10 | USER root 11 | 12 | WORKDIR /opt/irisapp 13 | RUN chown ${ISC_PACKAGE_MGRUSER}:${ISC_PACKAGE_IRISGROUP} /opt/irisapp 14 | 15 | USER irisowner 16 | 17 | COPY Installer.cls . 18 | COPY src src 19 | COPY irissession.sh / 20 | SHELL ["/irissession.sh"] 21 | 22 | RUN \ 23 | do $SYSTEM.OBJ.Load("Installer.cls", "ck") \ 24 | set sc = ##class(App.Installer).setup() 25 | 26 | # bringing the standard shell back 27 | SHELL ["/bin/bash", "-c"] 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 InterSystems Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Installer.cls: -------------------------------------------------------------------------------- 1 | Class App.Installer 2 | { 3 | 4 | XData setup 5 | { 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | } 25 | 26 | ClassMethod setup(ByRef pVars, pLogLevel As %Integer = 3, pInstaller As %Installer.Installer, pLogger As %Installer.AbstractLogger) As %Status [ CodeMode = objectgenerator, Internal ] 27 | { 28 | #; Let XGL document generate code for this method. 29 | Quit ##class(%Installer.Manifest).%Generate(%compiledclass, %code, "setup") 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IDP DV 2 | 3 | ## Instalation 4 | 5 | To install IDP.DV, you just need to dowload and import the package [IDP.DV](https://github.com/intersystems-ru/CDV/releases) file. 6 | Some ways to import IDP package: 7 | - Go to Management Portal -> System Explorer -> Classes -> Import and select the XML file. 8 | - Drag the file over Studio 9 | - Terminal command: 10 | 11 | ``` 12 | Do $system.OBJ.Load("yourpath/IDP.DV.xml","ck") 13 | ``` 14 | 15 | ## Docker 16 | 17 | To install using Docker. Follow this instructions: 18 | 19 | Open terminal and clone the repo into any local directory 20 | 21 | ``` 22 | $ git clone https://github.com/intersystems-ru/CDV.git 23 | ``` 24 | 25 | Open the terminal in this directory and run: 26 | 27 | ``` 28 | $ docker-compose build 29 | ``` 30 | 31 | Run the IRIS container with your project: 32 | ``` 33 | $ docker-compose up -d 34 | ``` 35 | 36 | ### How to Run the Application 37 | Open InterSystems IRIS terminal: 38 | 39 | ``` 40 | $ docker-compose exec iris iris session iris 41 | USER>zn "IRISAPP" 42 | IRISAPP>set st = ##class(IDP.DV).ScanAllClasses(.Oid) 43 | IRISAPP>zw Oid 44 | ``` 45 | 46 | ## Usage 47 | 48 | s st = ##class(IDP.DV).ScanAllClasses(.Oid) - for all user classes 49 | s st = ##class(IDP.DV).ScanSubclassesOf(Class, .Oid) - for subclasses 50 | s st = ##class(IDP.DV).ScanMatchingClasses(Mask, .Oid) - for LIKE SQL 51 | 52 | The utility works only in a current namespace. 53 | 54 | Arguments: 55 | 56 | - `Oid` - Output structure, that stores data about invalid objects in a classes 57 | - `Class` - Scan all subclasses Of a class (and class itself). 58 | - `Mask` - Passed into the SQL query `SELECT ID FROM %Dictionary.ClassDefinition Where ID LIKE ?` 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/cls/IDP/DV.cls: -------------------------------------------------------------------------------- 1 | Class IDP.DV 2 | { 3 | 4 | ClassMethod ScanAllClasses(ByRef Oid As %String) As %Status 5 | { 6 | #Dim sc As %Status = $$$OK 7 | set sc = $System.OBJ.GetClassList(.Classes, "/application=0 /system=0 /percent=0 /mapped=0") 8 | Quit:$$$ISERR(sc) 9 | Set sc = ..ScanClassLocal(.Classes, .Oid) 10 | Quit sc 11 | } 12 | 13 | ClassMethod ScanSubclassesOf(Class As %String, ByRef Oid As %String) As %Status 14 | { 15 | #Dim sc As %Status = $$$OK 16 | Set RS = ##class(%ResultSet).%New("%Dictionary.ClassDefinition:SubclassOf") 17 | Set sc = RS.%Execute(Class) 18 | Quit:$$$ISERR(sc) 19 | 20 | Set Classes(Class) = "" 21 | 22 | While (RS.%Next(.sc)) { 23 | Quit:$$$ISERR(sc) 24 | Set Classes(RS.Data("Name")) = "" 25 | } 26 | 27 | Set sc = ..ScanClassLocal(.Classes, .Oid) 28 | Quit sc 29 | } 30 | 31 | ClassMethod ScanMatchingClasses(Mask As %String, ByRef Oid As %String) As %Status 32 | { 33 | #Dim sc As %Status = $$$OK 34 | 35 | Set SQL = "SELECT ID FROM %Dictionary.ClassDefinition Where ID LIKE ?" 36 | Set ST = ##class(%SQL.Statement).%New() 37 | Set sc = ST.%Prepare(SQL) 38 | Quit:$$$ISERR(sc) sc 39 | 40 | #Dim RS As %SQL.StatementResult 41 | Set RS = ST.%Execute(Mask) 42 | 43 | While RS.%Next() { 44 | Set Classes(RS.%GetData(1)) = "" 45 | } 46 | 47 | Set sc = ..ScanClassLocal(.Classes, .Oid) 48 | Quit sc 49 | } 50 | 51 | ClassMethod ScanClassLocal(ByRef Classes As %String, ByRef Oid As %String) As %Status 52 | { 53 | #Dim sc,sc1 As %Status = $$$OK 54 | Set Class = "" 55 | For { 56 | Set Class = $Order(Classes(Class)) 57 | Quit:Class="" 58 | If (##class(%Dictionary.CompiledClass).%ExistsId(Class) && $classmethod(Class, "%Extends", "%Library.Persistent")) 59 | { 60 | Set sc1 = ..ValidateClassObjects(Class, .Oid) 61 | } 62 | Set sc = $$$ADDSC(sc, sc1) 63 | } 64 | 65 | Quit sc 66 | } 67 | 68 | ClassMethod ValidateClassObjects(Class As %String, ByRef Oid As %String) As %Status 69 | { 70 | #Dim sc As %Status = $$$OK 71 | 72 | w !,"__________________________________________________________________________________",! 73 | set Oid(Class) = 0 74 | set query = ##class(%SQL.Statement).%New() 75 | set sc = query.%PrepareClassQuery(Class,"Extent") 76 | return:$$$ISERR(sc) sc 77 | set rset=query.%Execute() 78 | 79 | While (rset.%Next()) 80 | { 81 | set obj = $classmethod(Class, "%OpenId", rset.%Get("ID")) 82 | do $system.CLS.SetModified(obj, 1) 83 | 84 | set sc = obj.%ValidateObject() 85 | if $$$ISERR(sc) 86 | { 87 | w !,"Class: ",Class,!,"Object: ", rset.%Get("ID"),! 88 | w "-----------------------------------------------" 89 | do $system.Status.DisplayError(sc) 90 | w !,!,! 91 | set Oid(Class) = Oid(Class) + 1 92 | set Oid(Class, rset.%Get("ID")) = sc 93 | } 94 | Kill obj, valid 95 | } 96 | w !,Class, " has ",Oid(Class)," invalid objects " 97 | set Oid(Class) = "has "_Oid(Class)_" invalid objects" 98 | Quit sc 99 | } 100 | 101 | } 102 | 103 | --------------------------------------------------------------------------------