initial commit

This commit is contained in:
Michael Becker 2024-05-04 23:28:41 -04:00
parent d7cb7dc88d
commit 9da10a15e7
71 changed files with 3182 additions and 110 deletions

View File

@ -0,0 +1,20 @@
# Mocha Local Server Configuration
- server:
- port: 8081
pathMappings:
- source: /
destination: /home/beckermj
defaultTenantName: default
assets:
- type: local
path: /usr/share/mocha/assets # /module/version/...path...
# these could even be .zip files of asset bundles
# which would be decompressed on-the-fly and streamed to the client
- type: remote
# for example
path: https://static.alcehosting.net/prod/mocha/assets
tenants:
- name: default
- name: starlight1
libraryReferences:
- filename: /usr/share/mocha/system/Mocha.System.mcl

View File

@ -0,0 +1,504 @@
#
# mocha-shell - the 'latte' python REPL shell for mocha
# Copyright (C) 2024 Michael Becker
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from mocha.core import InstanceKey, InstanceReference
from mocha.oms import Oms
from mocha.definitions import KnownClassGuids, KnownInstanceGuids, KnownAttributeGuids, KnownRelationshipGuids
from framework import REPLApplication, Guid, format_cwd, parse_cwd
import atexit
import colorama
import os
import readline
import sys
from colorama import Fore, Style
from getpass import getpass
configpath = os.path.join(os.path.expanduser("~"), ".config", "latte")
if not os.path.exists(configpath):
os.mkdir(configpath)
histfile = os.path.join(configpath, "history")
try:
readline.read_history_file(histfile)
# default history len is -1 (infinite), which may grow unruly
readline.set_history_length(1000)
except FileNotFoundError:
pass
atexit.register(readline.write_history_file, histfile)
colorama.init()
class MochaShell (REPLApplication):
def print_instance_list(self, instances : list):
print("")
print("instance key global identifier comment ")
print("--------------- -------------------------------------- -------------------------")
for inst in instances:
print(str(inst.get_instance_key()).ljust(16) + str(inst.get_global_identifier()) + " " + self.oms.get_instance_text(inst))
print("")
def print_instance_list_with_attribute_values(self, instances : list, oms : Oms, refobj : InstanceReference):
print("")
print("instance key global identifier value")
print("--------------- -------------------------------------- ---------")
for inst in instances:
print(str(inst.get_instance_key()).ljust(16) + str(inst.get_global_identifier()) + " " + str(oms.get_attribute_value(refobj, inst)))
print("")
def print_instance_list_with_relationship_values(self, instances : list, oms : Oms, refobj : InstanceReference):
print("")
print("instance key global identifier value")
print("--------------- -------------------------------------- ---------")
for inst in instances:
print(str(inst.get_instance_key()).ljust(16) + str(inst.get_global_identifier()) + " ", end = "")
rels = oms.get_related_instances(refobj, inst)
for rel in rels:
if rels.index(rel) > 0:
print (" ", end = "")
print(str(rel.get_instance_key()))
print("")
def print_error(self, text : str):
print (f"{Fore.RED}error: {Style.RESET_ALL}" + text)
def print_error_not_open(self):
self.print_error ("no database specified, use `create` or `open` first")
def __init__(self):
self.current_user = None
self.current_file = None
from mocha.oms.db.sqlite import SQLiteDatabaseOms
self.oms = SQLiteDatabaseOms()
def open_file(self, oms : Oms, filename : str):
if not os.path.exists(filename):
print ("file not found")
return False
oms.open(filename)
print("opening '" + filename + "'")
un = input("user name: ")
pw = getpass("password: ")
user = oms.get_user_by_username(un)
if user is not None:
hash = oms.get_attribute_value(user, oms.get_instance_by_global_identifier(KnownAttributeGuids.PasswordHash))
salt = oms.get_attribute_value(user, oms.get_instance_by_global_identifier(KnownAttributeGuids.PasswordSalt))
passsalt = str(pw + salt).encode("utf-8")
import hashlib
passhash = hashlib.sha512(passsalt).hexdigest()
if (hash == passhash):
self.current_user = un
self.current_file = filename
login = oms.create_instance_of(oms.get_instance_by_global_identifier(KnownClassGuids.UserLogin))
oms.assign_relationship(login, oms.get_instance_by_global_identifier(KnownRelationshipGuids.User_Login__has__User), user)
# oms.assign_relationship(user, oms.get_instance_by_global_identifier(KnownRelationshipGuids.User__for__User_Login), login)
token = Guid.create()
oms.set_attribute_value(login, oms.get_instance_by_global_identifier(KnownAttributeGuids.Token), str(token))
return True
print ("invalid user name or password")
self.current_file = None
oms.close()
return False
def strip(self, iid_or_gid : str) -> str:
if iid_or_gid[0] == "[" and iid_or_gid[-1] == "]":
return iid_or_gid[1:-1]
return iid_or_gid
def parse(self, iid_or_gid : str) -> InstanceReference:
if len(iid_or_gid) < 3:
return None
if iid_or_gid[0] == "[" and iid_or_gid[-1] == "]":
ik = InstanceKey.parse(self.strip(iid_or_gid))
return self.oms.get_instance_by_key(ik)
elif iid_or_gid[0] == "{" and iid_or_gid[-1] == "}":
ik = Guid.parse(iid_or_gid)
return self.oms.get_instance_by_global_identifier(ik)
def create_file(self, oms : Oms, filename : str):
self.oms.open(filename)
self.oms.init()
self.oms.close()
def before_start_internal(self):
print (f"latte v0.3 - {Fore.GREEN}Local Application Testing and Troubleshooting Environment{Style.RESET_ALL}")
if len(sys.argv) > 1:
if os.path.exists(sys.argv[1]):
self.current_file = sys.argv[1]
else:
print(f"{Fore.RED}error:{Style.RESET_ALL} file not found '" + sys.argv[1] + "'")
if input("would you like to create it? (Y/N) [N] > ").lower() == "y":
self.create_file(self.oms, sys.argv[1])
self.current_file = sys.argv[1]
if self.current_file is None:
self.print_error_not_open()
else:
self.open_file(self.oms, self.current_file)
print ("")
def get_prompt(self):
prompt = f"{Fore.GREEN}{Style.BRIGHT}" + os.getlogin() + f"@localhost{Style.RESET_ALL}:{Fore.BLUE}{Style.BRIGHT}" + format_cwd(os.getcwd()) + f"{Style.RESET_ALL}\n↳ latte "
if self.current_file is not None:
if self.current_user is not None:
prompt += f"{Fore.GREEN}" + self.current_user + f"{Style.RESET_ALL}" + "@"
prompt += f"{Fore.CYAN}" + self.current_file + f"{Style.RESET_ALL}" + " "
prompt += "> "
return prompt
def interactive_create_attribute(self, attr_class : InstanceReference):
att_Name = self.oms.get_instance_by_global_identifier(KnownAttributeGuids.Name)
name = input("name: ")
if name == "":
print("please specify a name")
return None
attr = self.oms.create_instance_of(attr_class)
self.oms.set_attribute_value(attr, att_Name, name)
return attr
def process_input(self, value, quotes):
if len(value) > 0:
if value[0] == "cd":
os.chdir(parse_cwd(value[1]))
elif value[0] == "ls":
os.system("ls --color=always")
elif value[0] == "open":
if len(value) == 2:
if value[1] == "database":
if len(value) > 2:
self.open_file(self.oms, value[2])
return
else:
print("usage: open database|tenant 'filename'")
elif value[1] == "tenant":
print("error: not implemented")
return
else:
# default to "open database ..."
self.open_file(self.oms, value[1])
return
else:
print("usage: open database|tenant 'filename'")
elif value[0] == "create":
if len (value) > 1:
self.create_file(self.oms, value[1])
self.open_file(self.oms, value[1])
else:
print("usage: create filename.mql")
# print ("error: no database open, use `open filename.mql` first")
elif value[0] == "instance":
if len(value) > 1:
if value[1] == "create":
if len(value) == 3:
iid = self.parse(value[2])
inst = self.oms.create_instance_of(iid)
print(inst)
else:
print("usage: instance create class_iid [index]")
elif value[1] == "get":
if len(value) == 3:
iid = self.parse(value[2])
print(iid)
elif value[1] == "list":
if not self.oms.is_open():
self.print_error_not_open()
return
ik_of = None
if len(value) > 2:
ik_of = self.parse(value[2])
instances = self.oms.get_instances(ik_of)
self.print_instance_list(instances)
else:
print("usage: instance create|get|list")
elif value[0] == "attribute":
if len(value) > 1:
if value[1] == "create":
if len(value) > 2:
if value[2] == "text" or value[2] == "richtext":
attrClass = self.oms.get_instance_by_global_identifier(KnownClassGuids.TextAttribute)
if value[2] == "richtext":
attrClass = self.oms.get_instance_by_global_identifier(KnownClassGuids.RichTextAttribute)
attr = self.interactive_create_attribute(attrClass)
if attr is None:
return
att_MaximumLength = self.oms.get_instance_by_global_identifier(KnownAttributeGuids.MaximumLength)
maxlen = input("maximum length (leave empty for infinite): ")
if maxlen != "":
self.oms.set_attribute_value(attr, att_MaximumLength, int(maxlen))
elif value[2] == "boolean":
attrClass = self.oms.get_instance_by_global_identifier(KnownClassGuids.BooleanAttribute)
attr = self.interactive_create_attribute(attrClass)
if attr is None:
return
elif value[2] == "numeric":
attrClass = self.oms.get_instance_by_global_identifier(KnownClassGuids.NumericAttribute)
attr = self.interactive_create_attribute(attrClass)
if attr is None:
return
att_MinimumValue = self.oms.get_instance_by_global_identifier(KnownAttributeGuids.MinimumValue)
att_MaximumValue = self.oms.get_instance_by_global_identifier(KnownAttributeGuids.MaximumValue)
if att_MinimumValue is None:
print("warning: numeric attribute `Minimum Value` is not defined")
else:
minimum_value = input("minimum value (empty for infinite): ")
if minimum_value != "":
self.oms.set_attribute_value(attr, att_MinimumValue, int(minimum_value))
if att_MaximumValue is None:
print("warning: numeric attribute `Maximum Value` is not defined")
else:
maximum_value = input("maximum value (empty for infinite): ")
if maximum_value != "":
self.oms.set_attribute_value(attr, att_MaximumValue, int(maximum_value))
else:
print("usage: attribute create text|boolean|numeric|date|xml|richtext")
else:
print("usage: attribute create text|boolean|numeric|date|xml|richtext")
if value[1] == "list":
if len(value) == 3:
inst_id = self.parse(value[2])
if inst_id is None:
print("invalid inst id " + value[2] + " (inst not found)")
return
attrs = self.oms.get_attributes(inst_id)
self.print_instance_list_with_attribute_values(attrs, self.oms, inst_id)
else:
print ("usage: attribute list instance_id")
elif value[1] == "get":
if len(value) == 4:
if not self.oms.is_open():
self.print_error_not_open()
return
inst_id = self.parse(value[2])
att_id = self.parse(value[3])
if inst_id is None:
print("invalid inst id " + self.strip(value[2]) + " (inst not found)")
return
if att_id is None:
print("invalid inst id " + self.strip(value[3]) + " (inst not found)")
return
value = self.oms.get_attribute_value(inst_id, att_id)
print(value)
else:
print("usage: attribute get inst_iid|inst_gid att_iid|att_gid")
elif value[1] == "set":
if len(value) == 5:
if not self.oms.is_open():
self.print_error_not_open()
return
inst_id = self.parse(value[2])
att_id = self.parse(value[3])
value = value[4]
if inst_id is None:
print("invalid inst id " + self.strip(value[2]) + " (inst not found)")
return
if att_id is None:
print("invalid inst id " + self.strip(value[3]) + " (inst not found)")
return
result = self.oms.set_attribute_value(inst_id, att_id, value)
if result.success:
print("ok")
else:
print ("error: " + result.message)
else:
print("usage: attribute set inst_iid|inst_gid att_iid|att_gid value")
else:
print("usage: attribute list|get|set")
elif value[0] == "relationship":
if value[1] == "list":
if len(value) == 3:
inst_id = self.parse(value[2])
if inst_id is None:
print("invalid inst id " + value[2] + " (inst not found)")
return
rels = self.oms.get_relationships(inst_id)
self.print_instance_list_with_relationship_values(rels, self.oms, inst_id)
else:
print ("usage: relationship list instance_id")
elif value[0] == "user":
if value[1] == "list":
ik_User = self.oms.get_instance_by_global_identifier(KnownClassGuids.User)
ik_UserName = self.oms.get_instance_by_global_identifier(KnownAttributeGuids.UserName)
users = self.oms.get_instances(ik_User)
if users is None:
self.print_error_not_open()
return
print ("user name ")
print ("---------------------")
for user in users:
user_name = self.oms.get_attribute_value(user, ik_UserName)
print(user_name)
return
elif value[1] == "set-password":
if len(value) > 2:
my_username = value[2]
my_user = self.oms.get_user_by_username(my_username)
if my_user is None:
print("passwd: user '" + my_username + "' does not exist")
return
print("Changing password for " + my_username + ".")
pw = getpass("New password: ")
pw2 = getpass("Confirm new password: ")
if pw == pw2:
self.oms.set_user_password(my_user, pw)
print("passwd: password updated successfully")
else:
print("Sorry, passwords do not match.")
return
elif value[0] == "close":
self.oms.close()
else:
print("invalid cmd '" + value[0] + "'")
if __name__ == '__main__':
prog = MochaShell()
prog.start()

View File

@ -0,0 +1,49 @@
from mocha.web.WebServer import WebServer
from mocha.oms import Oms
from mocha.oms.memory import MemoryOms
import sys
from getopt import getopt
if __name__ == "__main__":
port = 8081
libraries = [ ]
(opts, remaining) = getopt(sys.argv[1:], "p", [ "port=", "library=" ])
for opt in opts:
if opt[0] == "--port":
port = int(opt[1])
print("Mocha User Interface Service v2.1")
from mocha.web.manager import ServerManager
svrmgr = ServerManager()
if len(remaining) == 0:
print("error: no server configurations specified")
for library in remaining:
svrmgr.add_server_config(library)
svrmgr.start()
# from mocha.lib.LibraryManager import MochaLibraryManager
# manager = MochaLibraryManager()
# from mocha.lib.parser.YAMLLibraryParser import YAMLLibraryParser
# yamlmgr = YAMLLibraryParser(manager)
# print("loading entity definitions...")
# for library in remaining:
# print("\t" + library)
# yamlmgr.load_entity_definitions_from_file(library)
# print("loading instances...")
# for library in remaining:
# print("\t" + library)
# yamlmgr.load_instances_from_file(library)
# oms = MemoryOms()

View File

@ -9,8 +9,6 @@ class InstanceKey():
return InstanceKey(tup[0], tup[1])
def __init__(self, class_id : int, inst_id : int):
self.__class_id = class_id
self.__inst_id = inst_id
@ -23,7 +21,7 @@ class InstanceKey():
def __str__(self):
return str(self.get_class_index()) + '$' + str(self.get_instance_index())
def to_tuple(self):
return (self.__class_id, self.__inst_id)
def __eq__(self, other):
return self.__class_id == other.__class_id and self.__inst_id == other.__inst_id

View File

@ -1,8 +1,10 @@
from .InstanceKey import InstanceKey
from framework import Guid
class InstanceReference:
def __init__(self, dbid, inst_key : InstanceKey, global_id):
def __init__(self, dbid, inst_key : InstanceKey, global_id : Guid):
self.dbid = dbid
self.inst_key = inst_key
self.global_id = global_id
@ -14,7 +16,10 @@ class InstanceReference:
return self.inst_key
def get_global_identifier(self):
return self.global_id.lower()
return self.global_id
def __str__(self):
return str(self.inst_key) + ' ' + self.global_id
return str(self.inst_key) + ' ' + str(self.global_id)
def __repr__(self):
return str(self.inst_key) + ' ' + str(self.global_id)

View File

@ -0,0 +1,55 @@
from framework import Guid
"""
Represents the Text Attribute `Name`
"""
Name = Guid.parse("{9153A637-992E-4712-ADF2-B03F0D9EDEA6}")
"""
Represents the Text Attribute `Value`
"""
Value = Guid.parse("{041DD7FD-2D9C-412B-8B9D-D7125C166FE0}")
"""
Represents the Text Attribute `Debug Definition File Name`
"""
DebugDefinitionFileName = Guid.parse("{03bf47c7-dc97-43c8-a8c9-c6147bee4e1f}")
DebugDefinitionLineNumber = Guid.parse("{822be9b7-531d-4aa1-818a-6e4de1609057}")
DebugDefinitionColumnNumber = Guid.parse("{0f75c750-e738-4410-9b4e-deb422efc7aa}")
Singular = Guid.parse("F1A06573C4474D85B4E754A438C4A960")
Value = Guid.parse("041DD7FD2D9C412B8B9DD7125C166FE0")
CSSValue = Guid.parse("C0DD4A42F5034EB380347C428B1B8803")
RelationshipType = Guid.parse("71106B1219344834B0F6D894637BAEED")
LabelOverride = Guid.parse("{89b361e0-9f13-4fea-9b1e-6eca573bd6ba}")
Label = Guid.parse("69cdf8affcf24477b75d71593e7dbb22")
Order = Guid.parse("{49423f66-8837-430d-8cac-7892ebdcb1fe}")
MethodType = Guid.parse("{47ae57a9-7723-48a8-80f2-dd410d929e14}")
ClassName = Guid.parse("c7e8d78ecfac4dacae242ac67a0ba9d3")
ThemeName = Guid.parse("{8cfc012c-52fd-4a66-8b2f-1b9b5e4af474}")
"""
A Numeric Attribute specifying the maximum length of an input field.
"""
MaximumLength = Guid.parse("6d69fee2f2204aadab8901bfa491dae1")
TargetURL = Guid.parse("970F79A09EFE4E7D92869908C6F06A67")
UserName = Guid.parse("960FAF025C5940F791A720012A99D9ED")
PasswordHash = Guid.parse("F377FC294DF14AFB96434191F37A00A9")
PasswordSalt = Guid.parse("8C5A99BC40ED4FA2B23FF373C1F3F4BE")
Encoding = Guid.parse("a82f3c46055e4e129c5de40447134389")
ContentType = Guid.parse("34142FCB172C490AAF03FF8451D00CAF")
BackgroundColor = Guid.parse("B817BE3BD0AC4A60A98A97F99E96CC89")
ForegroundColor = Guid.parse("BB4B6E0DD9BA403D9E8193E8F7FB31C8")
IPAddress = Guid.parse("ADE5A3C3A84E4798BC5BE08F21380208")
Token = Guid.parse("da7686b638034f1597f67f8f3ae16668")
DebugDefinitionFileName = Guid.parse("03bf47c7dc9743c8a8c9c6147bee4e1f")
MinimumValue = Guid.parse('{bc90ffdf-9b6e-444a-a484-f9d06d7f3c31}')
MaximumValue = Guid.parse('{b9353b1c-2597-4097-96eb-449a6fafcdab}')

View File

@ -0,0 +1,126 @@
from framework import Guid
Class = Guid.parse("{B9C9B9B7-AD8A-4CBD-AA6B-E05784630B6B}")
Attribute = Guid.parse("{F9CD7751-EF62-4F7C-8A28-EBE90B8F46AA}")
Relationship = Guid.parse("{9B0A80F9-C325-4D36-997C-FB4106204648}")
InstanceDefinition = Guid.parse("{ee26f146-0b89-4cfe-a1af-ae6ac3533eae}")
Enumeration = Guid.parse("{70c3ee17-4d54-4342-9e7b-527cf73c93dd}")
# Attribute subclasses
TextAttribute = Guid.parse("{C2F36542-60C3-4B9E-9A96-CA9B309C43AF}")
BooleanAttribute = Guid.parse("{EA830448-A403-4ED9-A3D3-048D5D5C3A03}")
NumericAttribute = Guid.parse("{9DE86AF1-EFD6-4B71-9DCC-202F247C94CB}")
DateAttribute = Guid.parse("{0B7B1812-DFB4-4F25-BF6D-CEB0E1DF8744}")
RichTextAttribute = Guid.parse("{9e393eb5-0b2d-4c31-bc8c-419f9af8aee6}")
Element = Guid.parse("{91929595-3dbd-4eae-8add-6120a49797c7}")
ElementContent = Guid.parse("{f85d4f5e-c69f-4498-9913-7a8554e233a4}")
Translation = Guid.parse("{04A53CC8-3206-4A97-99C5-464DB8CAA6E6}")
TranslationValue = Guid.parse("{6D38E757-EC18-43AD-9C35-D15BB446C0E1}")
String = Guid.parse("{5AECB489-DBC2-432E-86AF-6BE349317238}")
StringComponent = Guid.parse("{F9E2B671-13F5-4172-A568-725ACD8BBFAB}")
ExtractSingleInstanceStringComponent = Guid.parse("{FCECCE4E-8D05-485A-AE34-B1B45E766661}")
InstanceAttributeStringComponent = Guid.parse("{623565D5-5AEE-49ED-A5A9-0CFE670507BC}")
Prompt = Guid.parse("{EC889225-416A-4F73-B8D1-2A42B37AF43E}")
TextPrompt = Guid.parse("{195DDDD7-0B74-4498-BF61-B0549FE05CF3}")
ChoicePrompt = Guid.parse("{5597AEEB-922D-48AF-AE67-DF7D951C71DB}")
InstancePrompt = Guid.parse("{F3ECBF1E-E732-4370-BE05-8FA7CC520F50}")
BooleanPrompt = Guid.parse("{a7b49c03-c9ce-4a79-a4b2-e94fc8cd8b29}")
Method = Guid.parse("{D2813913-80B6-4DD6-9AD6-56D989169734}")
# MethodCall = Guid.parse("{084A6D58-32C9-4A5F-9D2B-86C46F74E522}")
ConditionalEvaluationCase = Guid.parse("{ba18abdc-11ae-46af-850a-eb30280b0ffa}")
ConditionalSelectAttributeCase = Guid.parse("{a1115690-c400-4e3e-9c8f-24e2a9477e8f}")
AccessModifier = Guid.parse("{ca4fcc11-16c8-4872-a712-82e589d382ce}")
MethodBinding = Guid.parse("{CB36098E-B9BF-4D22-87FA-4186EC632C89}")
ReturnAttributeMethodBinding = Guid.parse("{30FB6BA6-2BBB-41D2-B91A-709C00A07790}")
ReturnInstanceSetMethodBinding = Guid.parse("{AADC20F9-7559-429B-AEF0-97E059295C76}")
Executable = Guid.parse("{6A1F66F7-8EA6-43D1-B2AF-198F63B84710}")
ExecutableReturningAttribute = Guid.parse("{50b2db7a-3623-4be4-b40d-98fab89d3ff5}")
ExecutableReturningInstanceSet = Guid.parse("{d5fbc5cb-13fb-4e68-b3ad-46b4ab8909f7}")
ExecutableReturningElement = Guid.parse("{a15a4f52-1f1a-4ef3-80a7-033d45cc0548}")
ExecutableReturningWorkData = Guid.parse("{a0365b76-ad1f-462e-84da-d6a1d5b9c88c}")
Event = Guid.parse("{ca727ecd-8536-4aeb-9e75-352dbb958767}")
WorkData = Guid.parse("{05e8f023-88cb-416b-913e-75299e665eb2}")
WorkSet = Guid.parse("{c4c171d8-994b-485b-b0ac-053d11b963ab}")
Parameter = Guid.parse("{1ab99be0-43f1-495a-b85e-ec38ea606713}")
ParameterAssignment = Guid.parse("{c7aa0c7c-50d8-44fd-9b05-a558a38a6954}") # 28
ElementContentDisplayOption = Guid.parse("{bd68052a-daa4-43b9-8965-d38095473170}")
ReportObject = Guid.parse("{ff7d5757-d9d9-48ab-ab04-5932e7341a90}")
Validation = Guid.parse("{3E45AA17-6E8E-41DB-9C94-E84B4B4176E8}")
ValidationClassification = Guid.parse("{8f43d578-a671-436b-afdc-c8689a5bd9b6}")
PrimaryObjectReportField = Guid.parse("{59EA0C72-4800-48BA-84A4-DDFE10E5F4D0}")
RelationshipReportField = Guid.parse("{FC4E3BB5-1EA7-44FF-B828-2EA54CDD4ABB}")
ReportField = Guid.parse("{655A04D9-FE35-4F89-9AAB-B8FA34989D03}")
AttributeReportField = Guid.parse("{C06E0461-A956-4599-9708-012C8FE04D94}")
Module = Guid.parse("{e009631d-6b9d-445c-95df-79f4ef8c8fff}")
Report = Guid.parse("{19D947B6-CE82-4EEE-92EC-A4E01E27F2DB}")
ReportColumn = Guid.parse("{BEFE99A1-B2EB-4365-A2C9-061C6609037B}")
StandardReport = Guid.parse("{FDF4A498-DE83-417D-BA01-707372125C8D}")
TaskCategory = Guid.parse("{e8d8060f-a20c-442f-8384-03488b63247f}")
Task = Guid.parse("{D4F2564B-2D11-4A5C-8AA9-AF52D4EACC13}")
UITask = Guid.parse("{BFD07772-178C-4885-A6CE-C85076C8461C}")
Tenant = Guid.parse("{703F9D65-C584-4D9F-A656-D0E3C247FF1F}")
User = Guid.parse("{9C6871C1-9A7F-4A3A-900E-69D1D9E24486}")
UserLogin = Guid.parse("{64F4BCDB-38D0-4373-BA30-8AE99AF1A5F7}")
MenuItemCommand = Guid.parse("{9D3EDE23-6DB9-4664-9145-ABCBD3A0A2C2}")
MenuItemSeparator = Guid.parse("{798DECAB-5119-49D7-B0AD-D4BF45807188}")
MenuItemHeader = Guid.parse("{1F148873-8A97-4409-A79B-C19D5D380CA4}")
MenuItemInstance = Guid.parse("{6E3AA9AF-96B9-4208-BEA9-291A72C68418}")
Style = Guid.parse("{A48C843A-B24B-4BC3-BE6F-E2D069229B0A}")
StyleRule = Guid.parse("{C269A1F3-E014-4230-B78D-38EAF6EA8A81}")
StyleClass = Guid.parse("{a725f089-7763-4887-af37-da52358c378c}")
Page = Guid.parse("{D9626359-48E3-4840-A089-CD8DA6731690}")
ContainerPageComponent = Guid.parse("{6AD6BD1C-7D1C-4AC9-9642-FEBC61E9D6FF}")
ButtonPageComponent = Guid.parse("{F480787D-F51E-498A-8972-72128D808AEB}")
HeadingPageComponent = Guid.parse("{FD86551E-E4CE-4B8B-95CB-BEC1E6A0EE2B}")
ImagePageComponent = Guid.parse("{798B67FA-D4BE-42B9-B4BD-6F8E02C953C0}")
PanelPageComponent = Guid.parse("{D349C489-9684-4A5A-9843-B906A7F803BC}")
ParagraphPageComponent = Guid.parse("{ADFF93CE-9E85-4168-A7D4-5239B99BE36D}")
SequentialContainerPageComponent = Guid.parse("{A66D9AE2-3BEC-4083-A5CB-7DE3B03A9CC7}")
SummaryPageComponent = Guid.parse("{5EBA7BD6-BA0A-45B2-835C-C92489FD7E74}")
TabContainerPageComponent = Guid.parse("{E52B02D7-895C-4642-9B03-EB0232868190}")
DetailPageComponent = Guid.parse("{41F9508E-6CF0-4F3D-8762-FF17CD52C466}")
ElementPageComponent = Guid.parse("{122d5565-9df9-4656-b6af-ba5df6630d32}")
IntegrationID = Guid.parse("{49a5ebda-baaa-4ede-bba5-decc250ce1a3}")
IntegrationIDUsage = Guid.parse("{86084b9f-3860-4857-a41f-2f8b6877aff1}")
Dashboard = Guid.parse("{896B529C-452D-42AC-98C5-170ED4F826C6}")
DashboardContent = Guid.parse("{2720ea77-cb09-4099-9f74-ccdacdd146e8}")
Instance = Guid.parse("{263C4882-945F-4DE9-AED8-E0D6516D4903}")
InstanceSet = Guid.parse("{53aac86e-ce60-4509-a869-417c38c305e0}")
AuditLine = Guid.parse("{a4124a76-02f6-406a-9583-a197675b493b}")
Theme = Guid.parse("{7c2cc4b5-8323-4478-863b-1759d7adf62e}")
CommonBoolean = Guid.parse("{5b025da3-b7bd-45a9-b084-48c4a922bf72}")
CommonInstanceSet = Guid.parse("{3382da21-4fc5-45dc-bbd1-f7ba3ece1a1b}")

View File

@ -0,0 +1,14 @@
from framework import Guid
class User:
superuser = Guid.parse("{69e291d8-381b-4ad8-9013-f3b0a0c693fe}")
zq_environments = Guid.parse("{B066A54B-B160-4510-A805-436D3F90C2E6}")
zq_developer = Guid.parse("{098DDA82-CD04-4B53-8C75-89D420EA6902}")
zq_support = Guid.parse("{232A8CBF-0D2B-4BDA-BE86-3E2FA25A3FB5}")
zq_configurator = Guid.parse("{FB20A79C-EAA2-4A98-A1DA-BDC351854694}")
zq_implementer = Guid.parse("{63F2EF51-DC73-48EC-856A-6FBBEDE01A8A}")
admin = Guid.parse("{739C26BC-740F-4CB0-BCB1-2A28FA570E7D}")

View File

@ -0,0 +1,354 @@
from framework import Guid
Instance__has__Source_Definition = Guid.parse("{57cbc351-0428-47e6-a6db-445e4503abab}")
Class__has_super__Class = Guid.parse("{100F0308-855D-4EC5-99FA-D8976CA20053}")
Class__has_sub__Class = Guid.parse("C14BC80D879C4E6F9123E8DFB13F4666")
Class__has__Method = Guid.parse("2DA282715E464472A6F5910B5DD6F608")
Method__for__Class = Guid.parse("76D2CE0DAA4D460BB8442BD76EF9902B")
Class__has__Instance = Guid.parse("7EB41D3C2AE9488483A4E59441BCAEFB")
Instance__for__Class = Guid.parse("494D5A6D04BE477B8763E3F57D0DD8C8")
Class__has__Relationship = Guid.parse("3997CAAD3BFA4EA69CFA2AA63E20F08D")
Relationship__for__Class = Guid.parse("C00BD63F10DA4751B8EA0905436EA098")
Class__has_title__Translation = Guid.parse("B8BDB90569DD49CDB5570781F7EF2C50")
Class__has__Attribute = Guid.parse("DECBB61A2C6C4BC890420B5B701E08DE")
Attribute__for__Class = Guid.parse("FFC8E435B9F844958C854DDA67F7E2A8")
Class__has_default__Task = Guid.parse("CF396DAA75EA41488468C66A71F2262D")
Class__has_owner__User = Guid.parse("D1A25625C90F4A73A6F2AFB530687705")
User__owner_for__Class = Guid.parse("04DD2E6BEA5748408DD5F0AA943C37BB")
Instance__for__Module = Guid.parse("c60fda3c2c0a422980e8f644e4471d28")
Module__has__Instance = Guid.parse("c3e5d7e35e114f8da212b175327b2648")
Class__has__Object_Source = Guid.parse("B62F9B81799B4ABEA4AF29B45347DE54")
Object_Source__for__Class = Guid.parse("FBB9391DC4A243269F857801F377253C")
Relationship__has_source__Class = Guid.parse("7FB5D234042E45CBB11DAD72F8D45BD3")
Relationship__has_destination__Class = Guid.parse("F220F1C204994E87A32EBDBF80C1F8A4")
Relationship__has_sibling__Relationship = Guid.parse("656110FF450248B8A7F3D07F017AEA3F")
Translation__has__Translation_Value = Guid.parse("F9B60C00FF1D438FAC746EDFA8DD7324")
Translation_Value__has__Language = Guid.parse("3655AEC2E2C94DDE8D980C4D3CE1E569")
String__has__String_Component = Guid.parse("3B6C4C25B7BC42428ED1BA6D01B834BA")
Extract_Single_Instance_String_Component__has__Relationship = Guid.parse("5E499753F50F4A9EBF53DC013820499C")
Instance_Attribute_String_Component__has__Attribute = Guid.parse("E15D427769FB4F1992DB8D087F361484")
String_Component__has_source__Method = Guid.parse("1ef1c965e12048beb682aa040573b5fb")
# Class__instance_labeled_by__String = Guid.parse("F52FC851D65548A9B526C5FE0D7A29D2")
Class__instances_labeled_by__Executable_returning_Attribute = Guid.parse("{c22fc17f-0c92-47dc-9a8b-28db0db68985}")
Class__has_summary__Report_Field = Guid.parse("D11050AD73764AB784DEE8D0336B74D2")
Class__uses_preview__Executable_returning_Element = Guid.parse("{059dc948-5f1b-4331-94f4-6d79dc324ebf}")
Executable_returning_Element__preview_used_by__Class = Guid.parse("{07d5e08f-fe38-49fd-8fcb-c862a532ec57}")
Class__has_related__Task = Guid.parse("4D8670E12AF14E7C9C87C910BD7B319B")
Report_Object__has__Report_Field = Guid.parse("0af6265642bc40a5b0bcdbba67c347f6")
Report_Field__for__Report_Object = Guid.parse("b46c8caa3f46465fba117d6f385425a2")
Task__has_title__Translation = Guid.parse("D97AE03C261F4060A06D985E26FA662C")
Task__has_instructions__Translation = Guid.parse("A93878989DC0400694F11FB02EB3ECD7")
Task__has__Prompt = Guid.parse("929B106F7E3E4D30BB84E450A4FED063")
Task__has__Task_Category = Guid.parse("84048159430d4f6c9361115c8629c517")
Task__executes__Method_Call = Guid.parse("D8C0D4D4F8C64B92A2C18BF16B16203D")
Task__has_preview_action_title__Translation = Guid.parse("3f65ce0211dd4829a46bb9ea1b43e56a")
Prompt__has__Report_Field = Guid.parse("922CCB0561EA441D96E063D58231D202") # 3de784b9456142f0946fb1e90d80029e
Report_Field__for__Prompt = Guid.parse("5DED3DB4686445A9A5FF8E5A35AD6E6F") # b5f59216a1f149798642a4845e59daa8
Instance_Prompt__has_valid__Class = Guid.parse("D5BD754BF4014FD8A70782684E7E25F0")
Instance_Prompt_Value__has__Instance = Guid.parse("512B518EA89244ABAC354E9DBCABFF0B")
Method__executed_by__Method_Binding = Guid.parse("D52500F114214B739987223163BC9C04")
Method_Binding__executes__Method = Guid.parse("B782A5928AF542288296E3D0B24C70A8")
Method__has_return_type__Class = Guid.parse("1241c599e55d4dcf9200d0e48c217ef8")
Method_Binding__has__Parameter_Assignment = Guid.parse("2493810994f1463a9314c49e667cf45b")
Parameter_Assignment__for__Method_Binding = Guid.parse("19c4a5dbfd2644b8b431e081e6ffff8a")
Parameter_Assignment__assigns_from__Executable_returning_Work_Data = Guid.parse("{6f3687ed-7d88-4ece-914e-c47c57c1146d}")
Parameter_Assignment__assigns_to__Work_Data = Guid.parse("{51c37636-35d2-4528-99ca-50cf09fa1427}")
Parameter__has_data_type__Instance = Guid.parse("ccb5200c5faf4a3a9e8e2edf5c2e0785")
Instance__data_type_for__Parameter = Guid.parse("ea1e6305b2e44ba591b41ecfbebfa490")
Instance_Set__has__Instance = Guid.parse("7c9010a269f1402999c872e05c78c41e")
Parameter_Assignment__assigns_to__Parameter = Guid.parse("a6d30e787bff4fccb109ee96681b0a9e")
Parameter__assigned_from__Parameter_Assignment = Guid.parse("2085341e5e7e4a7fbb8ddfa58f6030d9")
Method_Binding__assigned_to__Parameter_Assignment = Guid.parse("cbcb23b710c449eba1cab9da73fe8b83")
Parameter_Assignment__assigns_from__Method_Binding = Guid.parse("1e055d30a96849d893fe541994fc0c51")
Validation__has__Validation_Classification = Guid.parse("BCDB6FFDD2F24B63BD7E9C2CCD9547E0")
Validation__has_true_condition__Executable = Guid.parse("AA2D3B5141534599A9836B4A13ADCBCB")
Validation__has_false_condition__Executable = Guid.parse("419047F8852B4A4DB161A8BD022FD8EB")
Validation__has_failure_message__Translation = Guid.parse("E15A97DD2A1D4DC0BD6BA957B63D9802")
Translation__failure_message_for__Validation = Guid.parse("46a7dfcb884847d59ad3d27fbd8b423f")
Build_Attribute_Method__returns__Attribute = Guid.parse("{dadbf0f3-7af0-4387-a6b7-a1724a216d88}")
# Build_Attribute_Method__builds_with__Executable_returning_Attribute = Guid.parse("{bb64cd83-85c2-4c20-82eb-2a5a5ead31f1}")
Build_Attribute_Method__builds_with__Build_Attribute_Method_Component = Guid.parse("{b4fad1b8-711c-4e84-82d0-e9a9e41e8aa7}")
Build_Attribute_Method_Component__uses__Executable_returning_Attribute = Guid.parse("{9d2acd01-5c6d-4a95-b77e-5261ba109540}")
Get_Attribute_Method__has__Attribute = Guid.parse("5eca9b3fbe754f6e8495781480774833")
Get_Referenced_Instance_Set_Method__returns__Work_Set = Guid.parse("{72057f5b-9b49-497d-852f-cd7e5e258d6c}")
Get_Referenced_Instance_Set_Method__uses_reference__Executable_returning_Instance_Set = Guid.parse("{2978238f-7cb0-4ba3-8c6f-473df782cfef}")
Get_Referenced_Instance_Set_Method__uses_answer__Executable_returning_Instance_Set = Guid.parse("{6a65819e-c8cb-4575-9af8-ee221364049b}")
Get_Referenced_Attribute_Method__returns__Attribute = Guid.parse("87f90fe95ec64b098f51b8a4d1544cae")
Get_Referenced_Attribute_Method__uses_reference__Executable_returning_Instance_Set = Guid.parse("{c7ecd498-6d05-4e07-b1bc-f7127d0d6666}")
Get_Referenced_Attribute_Method__uses_answer__Executable_returning_Attribute = Guid.parse("{022ccde3-2b9e-4573-a8fc-e7568f420cd3}")
Get_Specified_Instances_Method__returns__Work_Set = Guid.parse("{27796f3d-0cbd-42c5-a840-791d3af6c16d}")
Get_Specified_Instances_Method__uses__Instance = Guid.parse("dea1aa0b2bef4bacb4f90ce8cf7006fc")
Evaluate_Boolean_Expression_Method__returns__Boolean_Attribute = Guid.parse("{53cf2cb6-f5f2-499f-9f18-26b86bf671c4}")
Evaluate_Boolean_Expression_Method__has_source__Executable_returning_Work_Data = Guid.parse("{45d76d56-01ed-4641-9f68-cfe0c7d0d265}")
IDR_Evaluate_Boolean_Expression_Method__uses__Boolean_Operator = Guid.parse("{aa9e17a2-e4d9-4598-bcfc-2d729031d11c}")
Evaluate_Boolean_Expression_Method__has_target__Executable_returning_Work_Data = Guid.parse("{0646df91-7e3e-4d59-be71-b978a22ced8e}")
Prompt_Value__has__Prompt = Guid.parse("7CD62362DDCE4BFC87B9B5499B0BC141")
User__has_display_name__Translatable_Text_Constant = Guid.parse("6C29856C3B104F5BA291DD3CA4C04A2F")
User_Login__has__User = Guid.parse("85B40E4B849B4006A9C04E201B25975F")
User__has_default__Page = Guid.parse("f00cda6feded4e0fb6c59675ed664a75")
Dashboard__has__Dashboard_Content = Guid.parse("d26acf18afa54ccd8629e1d9dac394ed")
Dashboard_Content__for__Dashboard = Guid.parse("9f236d2d1f454096a69c42f37abbeebc")
Dashboard_Content__has__Instance = Guid.parse("1f0c40752b7d42c28488c7db06e91f5a")
Instance__for__Dashboard_Content = Guid.parse("376951c9252b48438e1dca89c94ddfa6")
Return_Instance_Set_Method_Binding__has_source__Class = Guid.parse("EE7A30498E09410C84CBC2C0D652CF40")
Report__has__Report_Column = Guid.parse("7A8F57F1A4F34BAF84A5E893FD79447D")
Report__has__Report_Data_Source = Guid.parse("1DE7B484F9E3476AA9D37D2A86B55845")
Report__has__Prompt = Guid.parse("5D112697303F419F886F3F09F0670B07")
Report_Column__has__Report_Field = Guid.parse("B90269107E914EE1B5F2D7B740614831")
Report_Column__has__Report_Column_Option = Guid.parse("41FFF5F0B4674986A6FD46FAF4A479E9")
Report_Data_Source__has_source__Method = Guid.parse("2D5CB496583946A09B9430D4E2227B56")
Report_Field__has_source__Method = Guid.parse("5db86b7669bf421f96e74c49452db82e")
Attribute_Report_Field__has_target__Attribute = Guid.parse("3796430126FD41D886611F73684C0E0A")
Relationship_Report_Field__has_target__Relationship = Guid.parse("134B2790F6DF4F979AB59878C4A715E5")
Tenant__has__Application = Guid.parse("22936f5126294503a30ba02d61a6c0e0")
Tenant__has_sidebar__Menu_Item = Guid.parse("D62DFB9F48D54697AAAD1CAD0EA7ECFA")
Tenant__has__Tenant_Type = Guid.parse("E94B6C9D330748589726F24B7DB21E2D")
Tenant__has_company_logo_image__File = Guid.parse("3540c81cb2294eacb9b59d4b4c6ad1eb")
Menu__has__Menu_Section = Guid.parse("a22d949ff8d14dcca3ebd9f910228dfd")
Menu_Item__has_title__Translatable_Text_Constant = Guid.parse("65E3C87EA2F74A339FA7781EFA801E02")
Menu_Section__has__Menu_Item = Guid.parse("5b659d7c58f9453c9826dd3205c3c97f")
Command_Menu_Item__has__Icon = Guid.parse("8859DAEF01F746FA8F3E7B2F28E0A520")
Instance_Menu_Item__has_target__Instance = Guid.parse("C599C20EF01A4B12A9195DC3B0F545C2")
Page__has_title__Translation = Guid.parse("7BE6522A4BE84CD38701C8353F7DF630")
Page__has__Style = Guid.parse("6E6E1A853EA94939B13ECBF645CB8B59")
Page__has__Page_Component = Guid.parse("24F6C596D77D4754B02300321DEBA924")
Style__has__Style_Rule = Guid.parse("4CC8A654B2DF4B17A95624939530790E")
Style_Rule__has__Style_Property = Guid.parse("B69C2708E78D413AB491ABB6F1D2A6E0")
Style__has_width__Measurement = Guid.parse("4930ca87641a426d9d67cda6d5f22303")
Style__has_height__Measurement = Guid.parse("978e6de0af7345a0bb56aaf451615b06")
Measurement__has__Measurement_Unit = Guid.parse("C97200821F40406D80B781C1B690354D")
Page__has_master__Page = Guid.parse("9bdbfd640915419f83fde8cf8bcc74ae")
Page__master_for__Page = Guid.parse("7fe8f2a2c94d401083aa9300cc99d71d")
Page_Component__has__Style = Guid.parse("818CFF507D4243B2B6A792C3C54D450D")
Style__for__Page_Component = Guid.parse("007563E7727744368C8206D5F156D8E1")
Button_Page_Component__has_text__Translatable_Text_Constant = Guid.parse("C25230B14D234CFE8B7556C33E8293AF")
Image_Page_Component__has_source__Method = Guid.parse("481E3FBEB82A4C769DDFD66C6BA8C590")
Sequential_Container_Page_Component__has__Sequential_Container_Orientation = Guid.parse("DD55F50687184240A89421346656E804")
Container_Page_Component__has__Page_Component = Guid.parse("CB7B81621C9E4E72BBB8C1C37CA69CD5")
Panel_Page_Component__has_header__Page_Component = Guid.parse("223B4073F41749CDBCA10E0749144B9D")
Panel_Page_Component__has_content__Page_Component = Guid.parse("AD8C5FAE24444700896EC5F968C0F85B")
Panel_Page_Component__has_footer__Page_Component = Guid.parse("56E339BD61894BACAB83999543FB8060")
Element_Page_Component__has__Element = Guid.parse("fe833426e25d4cde89392a6c9baac20c")
Element_Page_Component__has__Element_Content_Display_Option = Guid.parse("74e3c13a04fd4f49be7005a32cdcdfe7")
Element_Content_Display_Option__for__Element_Page_Component = Guid.parse("7d3a7045092549db9b7d24863c9848a6")
Element__for__Element_Page_Component = Guid.parse("963c5c60397947fab201a26839b9ded9")
Tenant__has_logo_image__File = Guid.parse("4C399E80ECA24A68BFB426A5E6E97047")
Tenant__has_background_image__File = Guid.parse("39B0D9634BE049C8BFA2607051CB0101")
Tenant__has_icon_image__File = Guid.parse("CC4E65BD7AAA40DAAECAC607D7042CE3")
Tenant__has_login_header__Translatable_Text_Constant = Guid.parse("41D66ACBAFDE4B6F892DE66255F10DEB")
Tenant__has_login_footer__Translatable_Text_Constant = Guid.parse("A6203B6B5BEB4008AE49DB5E7DDBA45B")
Tenant__has_application_title__Translation = Guid.parse("7668343767ba46d9a5e72945be635345")
Tenant__has_mega__Menu = Guid.parse("cdd743cbc74a46719922652c7db9f2d8")
Tenant_Type__has_title__Translatable_Text_Constant = Guid.parse("79AAE09C5690471C84421B230610456C")
Prompt__has_title__Translatable_Text_Constant = Guid.parse("081ee211753443c499b524bd9537babc")
Report__has_title__Translatable_Text_Constant = Guid.parse("DF93EFB08B5E49E78BC0553F9E7602F9")
Report__has_description__Translatable_Text_Constant = Guid.parse("D5AA18A77ACD4792B0396C620A151BAD")
Report_Field__has_title__Translatable_Text_Constant = Guid.parse("6780BFC2DBC040AE83EEBFEF979F0054")
Content_Page_Component__gets_content_from__Method = Guid.parse("0E002E6FAA79457C93B82CCE1AEF5F7E")
Method__provides_content_for__Content_Page_Component = Guid.parse("5E75000D24214AD49E5FB9FDD9CB4744")
Securable_Item__secured_by__Method = Guid.parse("15199c4995954288846d13b0ad5dcd4b")
Get_Relationship_Method__has__Relationship = Guid.parse("321581d660c1454783449d5bda027adc")
Integration_ID__has__Integration_ID_Usage = Guid.parse("6cd30735df834253aabe360d6e1a3701")
Integration_ID_Usage__for__Integration_ID = Guid.parse("d8d981ec768640dab89f006c85042444")
Conditional_Select_from_Instance_Set_Method__has__Conditional_Select_from_Instance_Set_Case = Guid.parse("b6715132b4384073b81d3ecf19584b7d")
Conditional_Select_from_Instance_Set_Case__for__Conditional_Select_from_Instance_Set_Method = Guid.parse("1c868a068fb7432d839b7a5a02a50eb6")
Condition_Group__has_true_condition__Executable_returning_Attribute = Guid.parse("d955da3f7ef443748b86167c73434f75")
Executable_returning_Attribute__true_condition_for__Condition_Group = Guid.parse("1acdefd1e1b445bb99e1bf73dea71da5")
Condition_Group__has_false_condition__Executable_returning_Attribute = Guid.parse("e46dbc4fae8d4ad8b9e610cedfa68b73")
Executable_returning_Attribute__false_condition_for__Condition_Group = Guid.parse("633af008bf7f4da194d667a9a80586d6")
Audit_Line__has__Instance = Guid.parse("c91807ed0d734729990bd90750764fb5")
Audit_Line__has__User = Guid.parse("7c1e048d3dcb44739f2ee21014a76aa5")
Method__has__Method_Parameter = Guid.parse("c455dc79ba9b4a7caf8e9ca59dbe511f")
Method_Parameter__for__Method = Guid.parse("0bcb6e5b58854747843ced4c3d3dc234")
Method__returns__Attribute = Guid.parse("eb015d320d4f4647b9b8715097f4434b")
Detail_Page_Component__has_caption__Translation = Guid.parse("4a15fa44fb7b4e268ce2f36652792b48")
Element__has__Element_Content = Guid.parse("c1d3248102f948c6baf837d93fa8da23")
Element_Content__for__Element = Guid.parse("2eff7f580edd40b79c0600774257649e")
Element__has_label__Translation = Guid.parse("7147ea909f454bb9b151025b6e2bd834")
Element_Content__has__Instance = Guid.parse("315b71ba953d45fc87e54f0a268242a9")
Instance__for__Element_Content = Guid.parse("c3959f84248d4edea3f2f262917c7b56")
Element_Content__has__Layout = Guid.parse("1ab7412005ea4acab6d3c7e0133e0c4f")
Element_Content__has__EC_Dynamic_Display_Option = Guid.parse("{4a41391a-c325-4182-920a-a94ad28c15fa}")
EC_Dynamic_Display_Option__modifies__Element_Content = Guid.parse("{4d091643-2bfc-4b83-b3e4-8a3b22c665a9}")
Dynamic_Display_Option__add__Display_Option = Guid.parse("{2ed33b28-f84d-4120-b585-be965cfb691f}")
Dynamic_Display_Option__remove__Display_Option = Guid.parse("{dc06bf0b-70dd-4f71-854d-0f5685e2124f}")
Element_Content__built_from__BEM_Process = Guid.parse("{3d7094ff-33e5-4800-9e4e-93dde0d1d331}")
BEM_Process__uses_loop__Executable_returning_Instance_Set = Guid.parse("{0fb2b538-eacb-418a-b7d8-43a584b85952}")
Layout__has__Style = Guid.parse("{e684bb26-7e78-4a21-b8b4-5a550f3053d5}")
Rotary_Switch_Layout__has__Rotary_Switch_Layout_Option = Guid.parse("{ae716c95-1e26-48f4-9013-001d1a1854aa}")
Element_Content__has__Element_Content_Display_Option = Guid.parse("f070dfa762604488a779fae291903f2d")
Element_Content__has__Parameter_Assignment = Guid.parse("51214ef0458a44fa8b9df3d9d2309388")
Parameter__assigned_from__Element_Content = Guid.parse("dcef180ba2ca4d87bb05b946c319b562")
Element_Content__has__Validation = Guid.parse("265637cd2099416b88fa4f5ed88a87e3")
Validation__for__Element_Content = Guid.parse("3a4677e89c78414980ad46e5ac3b12f5")
Instance__has__Instance_Definition = Guid.parse("329c54ee17b84550ae80be5dee9ac53c")
Task__has_initiating__Element = Guid.parse("78726736f5b74466b11429cbaf6c9329")
Element__initiates_for__Task = Guid.parse("36964c5d348e4f888a620a795b43bc14")
Detail_Page_Component__has_row_source__Method_Binding = Guid.parse("54FBD0560BD444F4921C11FB0C77996E")
Detail_Page_Component__has_column_source__Method_Binding = Guid.parse("ddabeedaaa264d87a4574e7da921a293")
Work_Set__has_valid__Class = Guid.parse("0808746241a5427184bca9bcd31a2c21")
Class__valid_for__Work_Set = Guid.parse("73c65dcf781047d498c0898ca1b17a68")
Conditional_Select_Attribute_Method__returns__Attribute = Guid.parse("{b2b9d9cc-c4dd-491b-853e-e3669ea4e66a}")
Attribute__returned_by__Conditional_Select_Attribute_Method = Guid.parse("{e3e734ce-953b-49b8-b50d-b1826b519053}")
Conditional_Select_Attribute_Method__has__Conditional_Select_Attribute_Case = Guid.parse("{49396bd0-b5a9-4384-99f4-2126d80b3b66}")
Conditional_Select_Attribute_Case__for__Conditional_Select_Attribute_Method = Guid.parse("{38e2816e-ccb4-4e89-86ab-4981f5c2d7ac}")
Conditional_Select_Attribute_Case__invokes__Executable_returning_Attribute = Guid.parse("{dbd97430-9c55-430d-815c-77fce9887ba7}")
Executable_returning_Attribute__invoked_by__Conditional_Select_Attribute_Case = Guid.parse("{f4b04072-abe8-452a-b8f8-e0369dde24d4}")
Style__gets_background_image_File_from__Return_Instance_Set_Method_Binding = Guid.parse("4b4a0a3e426c4f70bc15b6efeb338486")
Style__has__Style_Class = Guid.parse("2cebd83052aa44ff818db2d6ee273a1f")
Style_Class__for__Style = Guid.parse("b2fbce51455a42b59fd1c28bb0cbe613")
Style__implements__Style = Guid.parse("99b1c16af2cb4cc5a3bb82a96335aa39")
Style__implemented_for__Style = Guid.parse("271ef8161e944f02a8054f9536c28dca")
Style__has_horizontal__Alignment = Guid.parse("{cc8d60e3-1b42-4ab1-a918-3d109891bb4e}")
Style__has_vertical__Alignment = Guid.parse("{24c175dd-c34c-4ffc-aef0-440aa032ceeb}")
Get_Attribute_by_System_Routine_Method__uses__System_Attribute_Routine = Guid.parse("{f7aaac2c-0bfd-4b31-8c8c-3a76e9522574}")
Get_Attribute_by_System_Routine_Method__returns__Attribute = Guid.parse("{e19cf181-b5bf-4595-b5c6-b9098a7a41bb}")
Get_Instance_Set_by_System_Routine_Method__uses__System_Instance_Set_Routine = Guid.parse("{085bd706-eece-4604-ac04-b7af114d1d21}")
System_Instance_Set_Routine__used_by__Get_Instance_Set_By_System_Routine_Method = Guid.parse("{6fb6534c-2a46-4d6d-b9df-fd581f19efed}")
Get_Instance_Set_by_System_Routine_Method__returns__Instance_Set = Guid.parse("{84a864fe-84de-4901-a51c-1e103dc56aed}")
System_Account__has__User_Preferences = Guid.parse("{ada4deb2-adfd-409f-b13a-9856fabd5522}")
User_Preferences__for__System_Account = Guid.parse("{ab2372a5-a4c7-488a-89f6-67e5834f8c83}")
Button_Layout__executes_task_from__Instance_Set = Guid.parse("04d104faa6c4425ea6cd56d847c63e9d")
Button_Layout__gets_related_instance_from__Instance_Set = Guid.parse("{462bb1ab-aefa-4455-8d56-eff233e3caa7}")
Element__processed_by__Process_Related_Updates_Method = Guid.parse("{ed9c836a-04a4-4505-8953-3c567e841c66}")
Element__processed_by__Control_Transaction_Method = Guid.parse("{0f182291-6784-47b3-a8d3-d2f6ebf3950c}")
Control_Transaction_Method__uses__Build_Response_Method_Binding = Guid.parse("{d8f2f0cc-54a2-4004-a383-8c1321495531}")
Build_Response_Method_Binding__used_by__Control_Transaction_Method = Guid.parse("{9b83d1f3-6569-4e98-9d88-765684abfd18}")
Process_Related_Updates_Method__uses__Executable_for_PUMB = Guid.parse("{50e1f14a-d6e5-4c71-b7ab-1755442728dc}")
Process_Related_Updates_Method__processes_for__Class = Guid.parse("{436a20fb-f672-4397-aca4-ec0ed6e2280a}")
Assign_Attribute_Method__uses__Executable_returning_Attribute = Guid.parse("{9313f96e-58af-416f-852e-ef83725057fc}")
Assign_Attribute_Method__assigns__Attribute = Guid.parse("{74061875-8a27-403b-9456-02e52cfd13b2}")
Get_Instances_Method__returns__Work_Set = Guid.parse("{7d0f93b1-8c93-464e-a44d-d674f910b589}")
Get_Instances_Method__selects_instances_of__Class = Guid.parse("{c0b85d90-de8c-44c2-9420-c5e724ccdf2c}")
Build_UI_Response_Method__uses__Executable_returning_Element = Guid.parse("{6f066ec6-b978-4627-81da-78fee1bed5e5}")
Executable_returning_Element__used_by__Build_UI_Response_Method = Guid.parse("{0e662556-ca79-43fe-9a50-57ad22df65de}")
Select_from_Instance_Set_Method__returns__Work_Set = Guid.parse("{e7805b49-0eb3-46ea-bc8a-a5ed676a7726}")
Work_Set__returned_by__Select_from_Instance_Set_Method = Guid.parse("{df12608a-e157-4a1b-bae2-0224a18f5b94}")
Select_from_Instance_Set_Method__uses__Executable_returning_Instance_Set = Guid.parse("{a907f814-b996-4294-b347-ca16ccaf1f5b}")
Executable_returning_Instance_Set__used_by__Select_from_Instance_Set_Method = Guid.parse("{a3ec06f9-54e8-4279-a31d-d221f8697a6a}")
Select_from_Instance_Set_Method__uses__Set_Function = Guid.parse("{abda76ae-a969-40e3-aed2-1a20fcec8b31}")
Set_Function__used_by__Select_from_Instance_Set_Method = Guid.parse("{753f9f4f-3fe3-470a-890d-d799c24e47af}")
Select_from_Instance_Set_Method__uses__Selection_Function = Guid.parse("{6498e72e-f321-4be2-acfd-dfd6f916ce54}")
Selection_Function__used_by__Select_from_Instance_Set_Method = Guid.parse("{e5e6a392-a436-41f7-bc80-cb6603503be1}")
Select_from_Instance_Set_Method__uses_function__Executable_returning_Attribute = Guid.parse("{30905c53-0d64-4332-9023-12a03e60cd09}")
Executable_returning_Attribute__function_used_by__Select_from_Instance_Set_Method = Guid.parse("{79adb5ea-0257-445b-9f7c-e5f8508a59a2}")
Select_from_Instance_Set_Method__uses_order__Executable_returning_Attribute = Guid.parse("{c7a5ef47-fce3-4e7c-87b8-f5cab93b1b10}")
Executable_returning_Attribute__order_used_by__Select_from_Instance_Set_Method = Guid.parse("{48c984ea-f4da-4090-bdd0-fd659b9be13d}")
Select_from_Instance_Set_Method__uses_subset_index__Executable_returning_Attribute = Guid.parse("{b5ef8d8b-683a-4cb9-9e6c-bc470324f4e3}")
Executable_returning_Attribute__as_subset_index_for__Select_from_Instance_Set_Method = Guid.parse("{7d03574f-db28-4aff-a96c-8013832b8269}")
Select_from_Instance_Set_Method__uses_comparator__Executable_returning_Work_Data = Guid.parse("{974c6e8b-b04f-4e3c-8719-298052afa9c7}")
Executable_returning_Work_Data__comparator_for__Select_from_Instance_Set_Method = Guid.parse("{c877ea85-ee9f-4e22-bae7-4a0d7b9272e1}")

View File

@ -0,0 +1,57 @@
from .Normalization import Normalization
from framework import Guid
class InstanceCache:
def __init__(self):
self.next_inst_id = dict()
self.next_inst_id[1] = 1
self.inst_indices = dict()
self.inst_guids = dict()
self.dbids_gid = dict()
def add_instance(self, inst_key, inst_gid):
self.inst_guids[inst_key] = inst_gid
self.inst_indices[inst_gid] = inst_key
if not inst_key[0] in self.next_inst_id:
self.next_inst_id[inst_key[0]] = 1
if inst_key[1] >= self.next_inst_id[inst_key[0]]:
self.next_inst_id[inst_key[0]] = inst_key[1] + 1
def get_global_identifier(self, inst_key):
return self.inst_guids[inst_key]
def get_instance_key(self, inst_gid):
return self.inst_indices[inst_gid]
def get_next_instance_id(self, class_index):
if not class_index in self.next_inst_id:
# this is the first instance of this class
self.next_inst_id[class_index] = 1
val = self.next_inst_id[class_index]
self.next_inst_id[class_index] += 1
return val
def has_instance_by_global_identifier(self, gid):
return gid in self.inst_indices
def count(self) -> int:
"""
Returns the number of instances stored in this OMS.
"""
return len(self.inst_indices)
def get_instance_keys(self):
return self.inst_indices
def set_database_id_by_global_identifier(self, gid : Guid, dbid):
self.dbids_gid[Normalization.normalize_uuid(gid.get_value())] = dbid
# self.dbids_idx[self.inst_indices[gid]] = dbid
def get_database_id_by_global_identifier(self, gid : Guid):
return self.dbids_gid[Normalization.normalize_uuid(gid.get_value())]

View File

@ -0,0 +1,442 @@
import MySQLdb
from .parser import XMLLibraryParser, JSONLibraryParser, YAMLLibraryParser
from .LibraryOperation import LibraryOperation
from .operations.AssignAttributeOperation import AssignAttributeOperation
from .operations.AssignRelationshipOperation import AssignRelationshipOperation
from .operations.PrepareInstanceOperation import PrepareInstanceOperation
from .operations.StoredProcedureOperation import StoredProcedureOperation
from .Normalization import Normalization
from framework import Guid
from mocha.definitions import KnownClassGuids, KnownAttributeGuids, KnownInstanceGuids, KnownRelationshipGuids
from .InstanceCache import InstanceCache
from .SQLExpression import SQLExpression
# from redis import Redis
class MochaLibraryManager:
def __init__(self):
self.entityReferences = dict()
self.entityReferenceFileNames = dict()
self.db = None
self._instances = []
self._attOps = []
self._relOps = []
self.redis = None
def connect(self, hostname, database, username, password):
self.db = MySQLdb.connect(host=hostname, user=username, passwd=password, db=database)
# self.redis = Redis(host=hostname, port=6379, decode_responses=True)
def process_instance_ops(self):
# this version is much faster as it prepares everything in advanced on the CPU before
# pushing it out to the database
instances = InstanceCache()
for key in self._instances:
(class_gid, inst_gid, class_index, inst_index) = key
# first import all the known classes
if class_gid is not None and class_index is not None:
# print ("known class import")
# print ("class_gid = " + class_gid)
# print ("inst_gid = " + inst_gid + " (" + str(class_index) + "$" + str(inst_index) + ")")
if not instances.has_instance_by_global_identifier(class_gid):
instances.add_instance((1, class_index), class_gid)
for key in self._instances:
(class_gid, inst_gid, class_index, inst_index) = key
# now get all the classes without specified IIDs
if class_gid is not None and class_index is None:
# print ("unknown class import")
if not instances.has_instance_by_global_identifier(class_gid):
class_index = instances.get_next_instance_id(class_index)
else:
class_index = instances.get_instance_key(class_gid)[1]
if inst_index is None:
inst_index = instances.get_next_instance_id(class_index)
instances.add_instance((1, inst_index), inst_gid)
# print ("class_gid = " + class_gid)
# print ("inst_gid = " + inst_gid + " (" + str(1) + "$" + str(inst_index) + ")")
for key in self._instances:
(class_gid, inst_gid, class_index, inst_index) = key
if class_gid is not None and class_index is not None and inst_gid is not None and inst_index is not None:
# we know all there is to know about this one
pass
elif class_gid is not None and inst_gid is not None:
if class_index is None:
# we need to know the class index
if instances.has_instance_by_global_identifier(class_gid):
class_index = instances.get_instance_key(class_gid)[1]
else:
class_index = instances.get_next_instance_id(1)
if inst_index is None:
# we need to know the instance index as well
if instances.has_instance_by_global_identifier(inst_gid):
inst_index = instances.get_instance_key(inst_gid)[1]
else:
inst_index = instances.get_next_instance_id(class_index)
else:
print("error: not implemened class_gid is None or inst_gid is None")
instances.add_instance((class_index, inst_index), inst_gid)
print (str(instances.count()) + " instances preloaded")
c = 0
query = "INSERT INTO mocha_instances (tenant_id, class_id, inst_id, global_identifier) VALUES "
for inst_gid in instances.get_instance_keys():
(class_index, inst_index) = instances.get_instance_key(inst_gid)
print("preparing inst " + str(class_index) + "$" + str(inst_index) + " with guid " + inst_gid)
inst_key_str = str(class_index) + "$" + str(inst_index)
if self.redis is not None:
self.redis.set(inst_key_str + ".gid", Normalization.normalize_uuid(inst_gid))
self.redis.set(inst_key_str + ".attributes.count", "0")
self.redis.set(inst_key_str + ".relationships.count", "0")
self.redis.set(Normalization.normalize_uuid(inst_gid) + ".iid", inst_key_str)
self.redis.set(Normalization.normalize_uuid(inst_gid) + ".attributes.count", "0")
self.redis.set(Normalization.normalize_uuid(inst_gid) + ".relationships.count", "0")
query += "(1, " + str(class_index) + ", " + str(inst_index) + ", '" + Normalization.normalize_uuid(inst_gid) + "')"
if c < instances.count() - 1:
query += ", "
c += 1
print ("process_instance_ops: query was: ")
print (query)
self.db.query(query)
self.instances = instances
return True
def process_attribute_ops(self, ops):
query = "INSERT INTO mocha_attributes (tenant_id, src_inst_id, att_inst_id, usr_inst_id, att_effective_date, att_value) VALUES "
for op in ops:
instanceId = op.instanceId
attributeInstanceId = op.attributeInstanceId
value = op.value
if attributeInstanceId.get_value() == "":
print("skipping invalid blank attribute")
continue
print (instanceId.get_value() + " : " + attributeInstanceId.get_value() + " = '" + str(value) + "'")
# query += "(1, " \
# + "mocha_get_instance_by_global_identifier('" + Normalization.normalize_uuid(instanceId.get_value()) + "'), " \
# + "mocha_get_instance_by_global_identifier('" + Normalization.normalize_uuid(attributeInstanceId.get_value()) + "'), " \
# + "NULL, NOW(), " + SQLExpression.normalize_parm(value) + ")"
query += "(1, " \
+ str(self.instances.get_database_id_by_global_identifier(instanceId)) + ", " \
+ str(self.instances.get_database_id_by_global_identifier(attributeInstanceId)) + ", " \
+ "NULL, NOW(), " + SQLExpression.normalize_parm(value) + ")"
if ops.index(op) < len(ops) - 1:
query += ", "
# op.execute(self.db)
print ("process_attribute_ops: query was: ")
print (query)
self.db.query(query)
def process_relationship_ops(self, ops):
query = "INSERT INTO mocha_relationships (tenant_id, source_inst_id, relationship_inst_id, destination_inst_id, user_inst_id, effective_date) VALUES "
for op in ops:
instanceId = op.instanceId
relationshipInstanceId = op.relationshipInstanceId
targetInstanceId = op.targetInstanceId
print (instanceId.get_value() + " : " + relationshipInstanceId.get_value() + " = " + targetInstanceId.get_value())
query += "(1, " \
+ str(self.instances.get_database_id_by_global_identifier(instanceId)) + ", " \
+ str(self.instances.get_database_id_by_global_identifier(relationshipInstanceId)) + ", " \
+ str(self.instances.get_database_id_by_global_identifier(targetInstanceId)) + ", " \
+ "NULL, NOW() )"
if ops.index(op) < len(ops) - 1:
query += ", "
# op.execute(self.db)
print ("process_relationship_ops: query was: ")
print (query)
self.db.query(query)
def before_commit(self):
"""
Called before the unstructured information is sorted and written to the database.
---
This is your last chance to add instances, set attributes, and assign
relationships before the compilation is finalized. After this stage, calls made
to modify the compilation are undefined and will almost certainly not do what you
want.
"""
self.write_debug_information()
def write_debug_information(self):
"""
Writes debugging information, such as entity definitions ('&IDC_...;') and source
code definitions (filename, line number, column number, etc.)
"""
print ("preparing debug information (use --no-debug or undefine DEBUG or etc. [NOT IMPLEMENTED] to turn off)")
for key in self.entityReferences:
val = self.entityReferences[key]
gidEntityDefinition = Guid.create()
self.add_instance(IDC_EntityDefinition, gidEntityDefinition, None, None)
self.set_attribute_value(gidEntityDefinition, IDA_Name, key)
self.set_attribute_value(gidEntityDefinition, IDA_Value, val)
gidSourceDefinition = Guid.create()
self.add_instance(IDC_SourceDefinition, gidSourceDefinition, None, None)
self.set_attribute_value(gidSourceDefinition, IDA_DebugDefinitionFileName, self.entityReferenceFileNames[key])
self.assign_relationship(gidEntityDefinition, IDR_Instance__has__Source_Definition, gidSourceDefinition)
# Source Definition.has X
# self.add_instance(KnownClassGuids.CLASS, Guid.parse("{dc0a5dd2-22e0-471f-87cf-a5ef1b764efa}"), 1, index)
# self.assign_relationship(instGid, Guid.parse("{dc0a5dd2-22e0-471f-87cf-a5ef1b764efa}"), targetInstanceId)
def commit(self):
self.before_commit()
# first record all the instances
if not self.process_instance_ops():
return False
print("reading database ids...")
query = "SELECT id, global_identifier FROM mocha_instances"
cur = self.db.cursor()
cur.execute(query)
rows = cur.fetchall()
for (dbid, gid) in rows:
self.instances.set_database_id_by_global_identifier(Guid(gid), dbid)
print("assigning attributes...")
self.process_attribute_ops(self._attOps)
print("assigning relationships...")
self.process_relationship_ops(self._relOps)
hasSiblingRelationships = dict()
for op in self._relOps:
relationshipKey = self.instances
if op.relationshipInstanceId.get_value() == "{656110FF-4502-48B8-A7F3-D07F017AEA3F}":
# Relationship.has sibling Relationship
hasSiblingRelationships[op.instanceId.get_value()] = op.targetInstanceId
siblingOps = []
for op in self._relOps:
if op.relationshipInstanceId.get_value() in hasSiblingRelationships:
siblingOp = AssignRelationshipOperation(op.targetInstanceId, hasSiblingRelationships[op.relationshipInstanceId.get_value()], op.instanceId)
siblingOps.append(siblingOp)
# print ("assigning sibling relationship " + siblingOp.instanceId.get_value() + " . " + siblingOp.relationshipInstanceId.get_value() + " = " + siblingOp.instanceId.get_value())
# siblingOp.execute(self.db)
print("assigning sibling relationships...")
self.process_relationship_ops(siblingOps)
print("setting creation user...")
cur = self.db.cursor()
# cur.execute("UPDATE mocha_instances SET user_inst_id = mocha_get_instance_by_global_identifier(mocha_normalize_uuid('{B066A54B-B160-4510-A805-436D3F90C2E6}'))")
cur.execute("UPDATE mocha_attributes SET usr_inst_id = " + str(self.instances.get_database_id_by_global_identifier(Guid.parse("{B066A54B-B160-4510-A805-436D3F90C2E6}"))))
cur.execute("UPDATE mocha_relationships SET user_inst_id = " + str(self.instances.get_database_id_by_global_identifier(Guid.parse("{B066A54B-B160-4510-A805-436D3F90C2E6}"))))
# rows = cur.fetchall()
# print(rows)
# print ("ok , applying `Class.has Instance`...")
# for row in rows:
# print(row)
# id = row[0]
# tenant_id = row[1]
# class_id = row[2]
# inst_id = row[3]
# global_identifier = row[4]
# if class_id is not None and id is not None:
# # Class.has Instance
# query2 = ("CALL mocha_assign_relationship (" +
# "mocha_get_instance_by_key(1, " + str(class_id) + "), " +
# "mocha_get_instance_by_global_identifier(mocha_normalize_uuid('7EB41D3C-2AE9-4884-83A4-E59441BCAEFB'))" + ", " +
# str(id) + ", NULL, NULL)")
# cur.execute(query2)
# # Instance.for Class
# query3 = ("CALL mocha_assign_relationship (" +
# str(id) + ", " +
# "mocha_get_instance_by_global_identifier(mocha_normalize_uuid('494D5A6D-04BE-477B-8763-E3F57D0DD8C8'))" + ", " +
# "mocha_get_instance_by_key(1, " + str(class_id) + "), NULL, NULL)")
# cur.execute(query3)
self.db.commit()
def close(self):
self.db.close()
def print_error(self, cur):
rows = cur.fetchall()
for row in rows:
if 'error_description' in row:
print (row['error_description'])
def select_tenant(self, tenantName):
cur = self.db.cursor()
cur.execute("CALL mocha_select_tenant(mocha_get_tenant_by_name('" + tenantName + "'))")
self.print_error(cur)
def release_tenant(self):
cur = self.db.cursor()
cur.execute("CALL mocha_release_tenant()")
self.print_error(cur)
def assign_relationship(self, instanceId : Guid, relationshipInstanceId : Guid, targetInstanceId : Guid):
print("-- assigning relationship " + relationshipInstanceId.get_value() + " = '" + targetInstanceId.get_value() + "'")
self._relOps.append(AssignRelationshipOperation(instanceId, relationshipInstanceId, targetInstanceId))
# self._relOps.append(AssignRelationshipOperation(instanceId, relationshipInstanceId, targetInstanceId))
# query = "CALL mocha_assign_relationship(mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + instanceId.get_value() + "')), mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + relationshipInstanceId.get_value() + "')), mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + targetInstanceId.get_value() + "')), NULL, NULL);"
# print(query)
# cur.execute(query)
# self.print_error(cur)
def set_attribute_value(self, instanceId : Guid, attributeInstanceId : Guid, value):
print("-- assigning attribute " + attributeInstanceId.get_value() + " = '" + str(value) + "'")
self._attOps.append(AssignAttributeOperation(instanceId, attributeInstanceId, value))
def install_from_path(self, path):
from glob import glob
xl = XMLLibraryParser(self)
jl = JSONLibraryParser(self)
yl = YAMLLibraryParser(self)
#xml_files = glob(path + "/**/*.xml", recursive=True)
#for xml_file in xml_files:
#s xl.load_file(xml_file)
#json_files = glob(path + "/**/*.json", recursive=True)
#for json_file in json_files:
# jl.load_file(json_file)
yaml_files = sorted(glob(path + "/**/*.yaml", recursive=True))
if len(yaml_files) == 0:
print ("no files found ; does the path exist?")
return 3
# first, load the entity defs
for yaml_file in yaml_files:
yl.load_entity_definitions_from_file(yaml_file)
try:
# then, load instance definitions (also loads sugar elements into memory for later use)
for yaml_file in yaml_files:
yl.load_instances_from_file(yaml_file)
# finally, apply syntactic sugar
yl.apply_sugar()
return True
except NameError as ex:
print (ex)
rgx = "&(.*);"
# go through and get all entity references across all files
import re
import fileinput
stuff = []
for yaml_file in yaml_files:
f = open(yaml_file, "r")
text = f.read()
matches = re.findall(rgx, text)
for match in matches:
stuff.append(match)
f.close()
missingEntities = []
for stuf in stuff:
if not stuf in self.entityReferences:
if not stuf in missingEntities:
missingEntities.append(stuf)
if len(missingEntities) > 0:
print("\nNOTE: there were undefined referenced entities:\n")
for missingEntity in missingEntities:
print("\t" + missingEntity)
print("\n")
return False
def exists_entity_reference(self, name):
return name in self.entityReferences
def register_entity_reference(self, name, value, filename = None):
self.entityReferences[name] = value
self.entityReferenceFileNames[name] = filename
def define_entity_reference(self, name):
return self.entityReferences[name]
def expand_entity_references(self, value):
insideName = False
name = ""
retval = ""
for i in range(0, len(value)):
if value[i] == "&":
insideName = True
elif value[i] == ';':
insideName = False
if name in self.entityReferences:
retval += self.define_entity_reference(name)
else:
raise NameError("unknown entity ref '" + name + "'")
name = ""
elif insideName:
name += value[i]
else:
retval += value[i]
return retval
def add_instance(self, classGid : Guid, instGid : Guid, classIndex : int, index : int):
print("adding instance for class '" + classGid.get_value() + "' with globalid '" + instGid.get_value() + "' [" + str(index) + "]")
self._instances.append((classGid.get_value(), instGid.get_value(), classIndex, index))
# assign relationship `Instance.for Class`
self.assign_relationship(instGid, Guid.parse("{494D5A6D-04BE-477B-8763-E3F57D0DD8C8}"), classGid)
# assign relationship `Class.has Instance`
self.assign_relationship(classGid, Guid.parse("{7EB41D3C-2AE9-4884-83A4-E59441BCAEFB}"), instGid)

View File

@ -0,0 +1,21 @@
import MySQLdb
from MySQLdb.connections import Connection
class LibraryOperation:
def build_query(self):
return ''
def print_error(self, cur):
rows = cur.fetchall()
for row in rows:
if 'error_description' in row:
print (row['error_description'])
def execute(self, db : Connection):
cur = db.cursor()
query = self.build_query()
print(query)
cur.execute(query)
self.print_error(cur)

View File

@ -0,0 +1,5 @@
class Normalization:
@staticmethod
def normalize_uuid(val : str):
val = val.replace("{", "").replace("}", "").replace("-", "").strip().lower()
return val

View File

@ -0,0 +1,47 @@
from framework import Guid
from .Normalization import Normalization
class SQLExpression:
@staticmethod
def sqlescape(parm : str):
return parm.replace("'", "\\'")
@staticmethod
def normalize_parm(parm : str):
query = ""
if parm == None:
query += "NULL"
elif isinstance(parm, Guid):
gid = None
if parm is not None:
gid = "'" + Normalization.normalize_uuid(parm.get_value()) + "'"
else:
gid = "NULL"
query += gid
elif isinstance(parm, str):
query += "'" + SQLExpression.sqlescape(str(parm)) + "'"
else:
query += str(parm)
return query
@staticmethod
def to_string(parm):
return SQLExpression.normalize_parm(parm)
@staticmethod
def array_to_string(parms):
i = 0
query = ''
for parm in parms:
query += SQLExpression.to_string(parm)
if i < len(parms) - 1:
query += ", "
i += 1
return query

View File

@ -0,0 +1,20 @@
from .SQLExpression import SQLExpression
class SQLFunctionCall (SQLExpression):
def __init__(self, funcname, parms):
self.name = funcname
self.parms = parms
def get_name(self):
return self.name
def get_parameters(self):
return self.parms
def get_parameter_list(self):
return SQLExpression.array_to_string(self.parms)
def __str__(self):
return self.get_name() + "(" + self.get_parameter_list() + ")"

View File

@ -0,0 +1,12 @@
from .SQLExpression import SQLExpression
class SQLParameter (SQLExpression):
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
def __str__(self):
return "@" + self.get_name()

View File

@ -0,0 +1,21 @@
from .StoredProcedureOperation import StoredProcedureOperation
from framework import Guid
from ..SQLParameter import SQLParameter
from ..SQLFunctionCall import SQLFunctionCall
class AssignAttributeOperation(StoredProcedureOperation):
def __init__(self, instanceId : Guid, attributeInstanceId : Guid, value):
self.instanceId = instanceId
self.attributeInstanceId = attributeInstanceId
self.value = value
def get_sp_name(self):
return "mocha_set_attribute_value"
def get_sp_parameters(self):
return [ SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.instanceId ]), SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.attributeInstanceId ]), str(self.value), None, None ]
#query = "CALL mocha_set_attribute_value(mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + instanceId.get_value() + "')), mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + attributeInstanceId.get_value() + "')), '" + str(value) + "', NULL, NULL);"
#print(query)
#cur.execute(query)
#self.print_error(cur)

View File

@ -0,0 +1,21 @@
from .StoredProcedureOperation import StoredProcedureOperation
from framework import Guid
from ..SQLParameter import SQLParameter
from ..SQLFunctionCall import SQLFunctionCall
class AssignRelationshipOperation(StoredProcedureOperation):
def __init__(self, instanceId : Guid, relationshipInstanceId : Guid, targetInstanceId : Guid):
self.instanceId = instanceId
self.relationshipInstanceId = relationshipInstanceId
self.targetInstanceId = targetInstanceId
def get_sp_name(self):
return "mocha_assign_relationship"
def get_sp_parameters(self):
return [ SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.instanceId ]), SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.relationshipInstanceId ]), SQLFunctionCall('mocha_get_instance_by_global_identifier', [ self.targetInstanceId ]), None, None ]
#query = "CALL mocha_set_attribute_value(mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + instanceId.get_value() + "')), mocha_get_instance_by_global_identifier(mocha_normalize_uuid('" + attributeInstanceId.get_value() + "')), '" + str(value) + "', NULL, NULL);"
#print(query)
#cur.execute(query)
#self.print_error(cur)

View File

@ -0,0 +1,17 @@
from .StoredProcedureOperation import StoredProcedureOperation
from ..SQLParameter import SQLParameter
from ..SQLFunctionCall import SQLFunctionCall
from ..core.Guid import Guid
class CreateClassOperation (StoredProcedureOperation):
def __init__(self, globalIdentifier : Guid, classIndex : int):
self.globalIdentifier = globalIdentifier
self.classIndex = classIndex
def get_sp_name(self):
return 'mocha_create_class'
def get_sp_parameters(self):
return [ self.classIndex, self.globalIdentifier, None, None, SQLParameter("dummy") ]

View File

@ -0,0 +1,17 @@
from .StoredProcedureOperation import StoredProcedureOperation
from ..core.Guid import Guid
from ..SQLParameter import SQLParameter
from ..SQLFunctionCall import SQLFunctionCall
class CreateInstanceOperation(StoredProcedureOperation):
def __init__(self, globalIdentifier : Guid, classIndex : int, instanceIndex : int):
self.globalIdentifier = globalIdentifier
self.classIndex = classIndex
self.instanceIndex = instanceIndex
def get_sp_name(self):
return 'mocha_create_instance'
def get_sp_parameters(self):
return [ self.globalIdentifier, self.classIndex, self.instanceIndex, None, None, SQLParameter('assigned_inst_id') ]

View File

@ -0,0 +1,36 @@
from .StoredProcedureOperation import StoredProcedureOperation
from framework import Guid
from ..SQLParameter import SQLParameter
from ..SQLFunctionCall import SQLFunctionCall
class PrepareInstanceOperation(StoredProcedureOperation):
def __init__(self, classGlobalIdentifier : Guid, globalIdentifier : Guid, classIndex : int, instanceIndex : int):
self.classGlobalIdentifier = classGlobalIdentifier
self.globalIdentifier = globalIdentifier
self.classIndex = classIndex
self.instanceIndex = instanceIndex
def get_sp_name(self):
return "mocha_prepare_instance"
def get_sp_parameters(self):
parms = []
globalId = None
if self.globalIdentifier is not None:
globalId = self.globalIdentifier
classGlobalId = None
if self.classGlobalIdentifier is not None:
classGlobalId = self.classGlobalIdentifier
strCid = None
if self.classIndex is not None:
strCid = self.classIndex
strIid = None
if self.instanceIndex is not None:
strIid = self.instanceIndex
return [strCid, strIid, classGlobalId, globalId, None, None, SQLParameter("p_assigned_inst_id")]

View File

@ -0,0 +1,23 @@
import MySQLdb
from ..LibraryOperation import LibraryOperation
from MySQLdb.connections import Connection
from ..SQLExpression import SQLExpression
from ..SQLParameter import SQLParameter
from ..SQLFunctionCall import SQLFunctionCall
class StoredProcedureOperation (LibraryOperation):
def get_sp_name(self):
return ''
def get_sp_parameters(self):
return []
def build_query(self):
query = "CALL " + self.get_sp_name() + "("
parms = self.get_sp_parameters()
query += SQLExpression.array_to_string(parms)
query += ")"
return query

View File

@ -0,0 +1,30 @@
from .LibraryParser import LibraryParser
class JSONLibraryParser (LibraryParser):
def cstyle_strip_comments(self, val):
val2 = ""
# possible values for comment: 0 = none, 1 = multiline, 2 = singleline
comment = 0
xr = iter(range(0, len(val) - 1))
for i in xr:
if val[i] == '\n' and comment == 2:
comment = 0
check = val[i:i+2]
if check == "/*" and comment == 0:
comment = 1
next(xr)
elif check == "*/" and comment == 1:
comment = 0
next(xr)
elif check == "//":
comment = 2
next(xr)
elif comment == 0:
val2 += val[i]
val2 += val[-1:]
return val2

View File

@ -0,0 +1,4 @@
class LibraryParser():
def __init__(self, manager):
self.__manager = manager

View File

@ -0,0 +1,5 @@
class MochaSyntaxError(RuntimeError):
def __init__(self, *args):
RuntimeError.__init__(self, args)
pass

View File

@ -0,0 +1,46 @@
from .LibraryParser import LibraryParser
from xml.dom import minidom, Node
from xml.dom.minidom import Entity
class XMLLibraryParser(LibraryParser):
def load_instance(self, xmlnode):
print("instance : [" + xmlnode.getAttribute("id") + "]")
def load_library(self, xmlnode):
"""
Loads a library from the specified XML node.
"""
raise NotImplementedError()
if xmlnode.tagName != "library":
return
id = xmlnode.getAttribute("id")
for child in xmlnode.childNodes:
if child.tagName == "instances":
for child2 in child.childNodes:
self.load_library_instance_from_xml(child)
def load_file(self, filename):
print("loading xml from " + filename + "... ")
dom = minidom.getDOMImplementation()
dt = dom.createDocumentType("mocha", "-//MBS//DTD Mocha 1.0 Dev//EN", "https://doctype.schemas.alcetech.net/Mocha/1.0/mocha-1.0.dtd")
dt.entities.setNamedItem(Entity("IDC_ReturnInstanceSetMethodBinding", "{AADC20F9-7559-429B-AEF0-97E059295C76}", None, None))
dom = minidom.parse(filename)
if (dom.documentElement.tagName != "mocha"):
print(filename + ": top-level tag is not 'mocha'")
return
for child in dom.documentElement.childNodes:
if child.nodeType == Node.ELEMENT_NODE:
if child.tagName == "libraries":
for child2 in child.childNodes:
self.load_library(child)
print ("\n")

View File

@ -0,0 +1,345 @@
from .LibraryParser import LibraryParser
from framework import Guid
from .MochaSyntaxError import MochaSyntaxError
class YAMLLibraryParser (LibraryParser):
def __init__(self, manager):
LibraryParser.__init__(self, manager)
self.yamlIds = dict()
self.templates = dict()
# these two are special reserved tagNames
# self.yamlIds["entityDefinitions"] = None
# self.yamlIds["instance"] = { }
self.manager = manager
self._instances_awaiting_sugar = []
def apply_sugar(self):
print("applying syntactic sugar to remaining instances...")
# _instances_also_awaiting_sugar = []
for inst in self._instances_awaiting_sugar:
print("applying sugar from '" + inst["from_file_name"] + "'")
self.load_instance(inst)
print("\n")
# do recursively until we're all out of instances awaiting sugar
# if len(self._instances_awaiting_sugar) > 0:
# self.apply_sugar()
def load_library(self, elem):
print("loading library from elem")
def load_tenant(self, elem):
print("loading tenant from elem")
def find_custom_tag_name(self, elem) -> (str, Guid):
# return tuple (tagname, value)
if "instance" in elem:
return ("instance", Guid.parse(self.manager.expand_entity_references(elem["instance"])))
for key in self.yamlIds:
if key in elem:
k = str(key)
v = Guid.parse(self.manager.expand_entity_references(elem[key]))
return (k, v)
return (None, None)
def load_entity_definitions_from_file(self, filename):
print("loading entity defs from " + filename)
import yaml
with open(filename, 'r') as file:
content = yaml.safe_load_all(file)
for doc in content:
for elem in doc:
if "entityDefinitions" in elem:
entities = elem["entityDefinitions"]
if not entities is None:
for entity in entities:
for key in entity:
if self.manager.exists_entity_reference(key):
print("duplicate entity definition: '" + key + "'")
exit(1)
self.manager.register_entity_reference(key, entity[key], filename)
def load_instance_with_template(self, elem, template):
(parentCreatorKey, parentInstanceId) = self.find_custom_tag_name(template)
(creatorKey, instanceId) = self.find_custom_tag_name(elem)
self.apply_template(elem, template, instanceId)
def assign_relationship_value(self, instanceId, rel, rel_iid, relationshipValue):
if (isinstance(relationshipValue, str)):
# single instance, this should be a GUID or entityref
# we should only need to refer to existing instance in this case
relationshipValueInst = Guid.parse(self.manager.expand_entity_references(relationshipValue))
if "instance" in rel:
self.manager.assign_relationship(instanceId, Guid.parse(self.manager.expand_entity_references(rel["instance"])), relationshipValueInst)
else:
print("no relationship instance specified for relationship sugar")
else:
# dynamically created instance
#FIXME: this 'instance' isn't always the tag name, this can be subject to customTagName as well!and should be processed accordingly
(relinst_key, relinst_iid) = self.find_custom_tag_name(relationshipValue)
if relinst_key is not None:
# for example, 'relinst_key' is 'elementContent' and 'relinst_iid' is '{8ECA14A4...}'
if rel_iid is not None:
print("found customTagName '" + str(relinst_key) + "' with value '" + str(relinst_iid.get_value()) + "'")
# relval = Guid.parse(self.manager.expand_entity_references(elem[customTagName]))
# we need to create the new instance and assign relationship
self.manager.assign_relationship(instanceId, rel_iid, relinst_iid)
else:
if "globalIdentifier" in relationshipValue:
globalIdentifier = Guid.parse(relationshipValue["globalIdentifier"])
else:
globalIdentifier = Guid.create()
print("creating new instance for relationship '%s' with globalid '%s'" % (rel_iid, globalIdentifier.get_value()))
createsInstanceOf = None
if "type" in relationshipValue:
print("found relationship override type '%s'" % (relationshipValue['type']))
createsInstanceOf = Guid.parse(self.manager.expand_entity_references(relationshipValue["type"]))
elif "customTagNameCreatesInstanceOf" in rel:
createsInstanceOf = Guid.parse(self.manager.expand_entity_references(rel["customTagNameCreatesInstanceOf"]))
if not createsInstanceOf is None:
# create the new instance
self.manager.add_instance(createsInstanceOf, globalIdentifier, None, None)
# assign relationships
self.manager.assign_relationship(instanceId, rel_iid, globalIdentifier)
# self.manager.assign_relationship(globalIdentifier, relationshipInstanceId, instanceId)
# FIXME: apply relationships from the parent class template
#? NOTE: You MUST specify 'registerForTemplate: yes' on the template definition for
#? sibling relationships to be properly applied!
if createsInstanceOf.get_value() in self.templates:
print("applying template for createsInstanceOf '%s'" % (createsInstanceOf.get_value()))
createsInstanceOfTemplate = self.templates[createsInstanceOf.get_value()]
self.apply_template(relationshipValue, createsInstanceOfTemplate, globalIdentifier)
else:
print("no template registered for createsInstanceOf '%s'" % (createsInstanceOf.get_value()))
else:
print ("neither createsInstanceOf nor override 'type' present for relationship value")
def apply_template(self, elem, template, instanceId):
if "value" in elem:
print("VALUE found in ELEM:")
print(elem["value"])
if "attributes" in template:
attrs = template["attributes"]
if isinstance(attrs, list):
for attr in attrs:
if "customTagName" in attr:
customTagName = attr["customTagName"]
if customTagName in elem:
attrinst = Guid.parse(self.manager.expand_entity_references(attr["instance"]))
attrval = elem[customTagName]
self.manager.set_attribute_value(instanceId, attrinst, attrval)
if "relationships" in template:
rels = template["relationships"]
for rel in rels:
if "instance" in rel:
rel_iid = rel["instance"] # the globalId of the relationship instance
else:
print("no relationship instance specified for relationship sugar")
continue
if "customTagName" in rel:
customTagName = rel["customTagName"]
if customTagName in elem:
relationshipValue = elem[customTagName]
if relationshipValue is None:
continue
if isinstance(relationshipValue, list):
# multiple instances
for v in relationshipValue:
self.assign_relationship_value(instanceId, rel, Guid.parse(self.manager.expand_entity_references(rel_iid)), v)
else:
self.assign_relationship_value(instanceId, rel, Guid.parse(self.manager.expand_entity_references(rel_iid)), relationshipValue)
def get_instance_sugar_for_elem(self, elem):
if "instance" in elem:
return (elem["instance"], "instance", None)
else:
for key in self.yamlIds:
# no 'instance', see if we
if key in elem:
template = self.yamlIds[key]
templateKey = key
return (elem[templateKey], templateKey, template)
return (None, None, None) # should never get here
def load_instance(self, elem, elemParent = None):
# 'class' and 'relationship' are both at the 'same level'
# so we can't define 'relationship' without first defining 'class'
# we could try to keep looping as long as we're still getting "unknown tag name"
# (instanceID is None), but we could get stuck that way...
# for now, let's just forward define important classes (e.g. IDC_Relationship)
# all of these problems could be avoided by simply
# LOADING EVERYTHING INTO MEMORY (like the .NET version does)
# and only committing to the DB at the very end
# this will resolve problems where we can't find instances, or use syntactic sugar
(globalIdentifier, templateKey, template) = self.get_instance_sugar_for_elem(elem)
print ("globalIdentifier = " + str(globalIdentifier) + ", templateKey = " + str(templateKey))
if template is None:
# no sugar
pass
customTagName = None
if "customTagName" in elem:
customTagName = elem["customTagName"]
self.yamlIds[customTagName] = elem
print("registering customTagName '" + customTagName + "'")
if "registerForTemplate" in elem:
if elem["registerForTemplate"] == True:
self.templates[self.manager.expand_entity_references(globalIdentifier)] = elem
print("registering elem for template")
classId = None
classIndex = None
if template is None and elemParent is not None:
template = elemParent
if template is not None:
if "instance" in template:
classId = Guid.parse(self.manager.expand_entity_references(template["instance"]))
else:
for key in self.yamlIds:
if key in template:
classId = Guid.parse(self.manager.expand_entity_references(template[key]))
break
if "index" in template:
classIndex = template["index"]
instanceId = None
creatorKey = None
if "instance" in elem:
if "templateOnly" in elem and elem["templateOnly"] == True:
# instanceId = None
instanceId = Guid.parse(self.manager.expand_entity_references(elem["instance"]))
else:
instanceId = Guid.parse(self.manager.expand_entity_references(elem["instance"]))
creatorKey = 'instance'
else:
for key in self.yamlIds:
if key in elem:
instanceId = Guid.parse(self.manager.expand_entity_references(elem[key]))
creatorKey = key
break
index = None
if "index" in elem:
index = elem["index"]
# else:
# print("index not found for element")
# print(elem)
if classId is None and instanceId is not None:
#!!! HACK HACK HACK !!!
classId = instanceId
if classIndex is None and index is None:
classIndex = 1
index = 1
print("WARNING: class hack used for instanceId " + instanceId.get_value() + " ( index " + str(classIndex) + "$" + str(index) + ")")
if instanceId is not None:
self.manager.add_instance(classId, instanceId, classIndex, index)
if creatorKey == 'class': #FIXME: remove this special-case behavior
print("creating class " + instanceId.get_value())
# # assign relationship `Instance.for Class`
# self.manager.assign_relationship(instanceId, Guid.parse('494D5A6D04BE477B8763E3F57D0DD8C8'), Guid.parse('B9C9B9B7AD8A4CBDAA6BE05784630B6B'))
# # assign relationship `Class.has Instance`
# self.manager.assign_relationship(Guid.parse('B9C9B9B7AD8A4CBDAA6BE05784630B6B'), Guid.parse('7EB41D3C2AE9488483A4E59441BCAEFB'), instanceId)
if "instances" in elem:
classInsts = elem["instances"]
for inst in classInsts:
self.load_instance(inst, elem)
else:
print("creating instance " + instanceId.get_value() + " (of class " + classId.get_value() + ")")
# # assign relationship `Instance.for Class`
# self.manager.assign_relationship(instanceId, Guid.parse('494D5A6D04BE477B8763E3F57D0DD8C8'), classId)
# # assign relationship `Class.has Instance`
# self.manager.assign_relationship(classId, Guid.parse('7EB41D3C2AE9488483A4E59441BCAEFB'), instanceId)
# self.manager.create_instance_of(classId, instanceId, classIndex, index)
if templateKey is not None:
if template is not None:
print("using template (" + templateKey + ")")
#print(template)
self.load_instance_with_template(elem, template)
else:
#print("ignoring '" + templateKey + "'")
pass
def load_instances_from_file(self, filename):
print("loading instances from " + filename)
import yaml
with open(filename, 'r') as file:
content = yaml.safe_load_all(file)
for doc in content:
for elem in doc:
if "entityDefinitions" in elem:
continue
elif "library" in elem:
self.load_library(filename, elem)
elif "tenant" in elem:
self.load_tenant(filename, elem)
else:
raise MochaSyntaxError("neither 'library' nor 'tenant' top level element found")
def load_library(self, filename, elem):
if "instances" in elem:
instances = elem["instances"]
for elem1 in instances:
if "instance" in elem1:
# this is an instance definition (no sugar), so just load it
self.load_instance(elem1)
else:
# this is a syntactic sugar definition, so store it for later use
elem1["from_file_name"] = filename
self._instances_awaiting_sugar.append(elem1)
def load_tenant(self, filename, elem):
pass

View File

@ -0,0 +1,4 @@
from .LibraryParser import LibraryParser
from .JSONLibraryParser import JSONLibraryParser
from .XMLLibraryParser import XMLLibraryParser
from .YAMLLibraryParser import YAMLLibraryParser

View File

@ -0,0 +1,294 @@
from ..core import InstanceKey, InstanceReference, TenantReference
from ..definitions import KnownClassGuids, KnownInstanceGuids, KnownAttributeGuids, KnownRelationshipGuids
from framework import Guid
from .OmsResult import OmsResult
class Oms:
def __init__(self):
pass
def get_user_by_username(self, username : str):
ik_User = self.get_instance_by_global_identifier(KnownClassGuids.User)
if ik_User is None:
print ("error: class `User` is not defined")
return None
users = self.get_instances(ik_User)
for user in users:
un = self.get_attribute_value(user, self.get_instance_by_global_identifier(KnownAttributeGuids.UserName))
if un == username:
return user
return None
def create_class(self, class_id : int, inst_id : int, name : str, global_identifier : Guid):
pass
def create_relationship(self, src_class : InstanceReference, type : str, dst_class : InstanceReference, singular : bool = False, sibling_relationship : InstanceReference = None, global_identifier : Guid = None):
ik_current = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.Relationship), global_identifier)
self.assign_relationship(ik_current, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_source__Class), src_class)
self.assign_attribute(ik_current, self.get_instance_by_global_identifier(KnownAttributeGuids.RelationshipType), type)
self.assign_relationship(ik_current, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_destination__Class), dst_class)
self.assign_attribute(ik_current, self.get_instance_by_global_identifier(KnownAttributeGuids.Singular), singular)
if sibling_relationship is not None:
self.assign_relationship(ik_current, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_sibling__Relationship), sibling_relationship)
return ik_current
def get_parent_class(self, instance : InstanceReference) -> InstanceReference:
ik = InstanceKey(1, instance.get_instance_key().get_class_index())
return self.get_instance_by_key(ik)
def assign_attribute(self, instance : InstanceReference, attribute : InstanceReference, value : str):
pass
def assign_relationship(self, instance : InstanceReference, relationship : InstanceReference, related_instances : InstanceReference|list):
pass
def get_attribute_value_internal(self, inst : InstanceReference, att : InstanceReference, default_value = None):
pass
def get_attribute_value(self, inst : InstanceReference, att : InstanceReference, default_value = None):
value = self.get_attribute_value_internal(inst, att, default_value)
if value is None:
return default_value
pclass = self.get_parent_class(att)
if pclass is not None:
if pclass.get_global_identifier() == KnownClassGuids.NumericAttribute:
return float(value)
return value
def set_attribute_value_internal(self, inst : InstanceReference, att : InstanceReference, value):
pass
def set_attribute_value(self, inst : InstanceReference, att : InstanceReference, value) -> OmsResult:
if inst is None or att is None:
return OmsResult(False, "no value specified for instance reference: inst | att")
pclass = self.get_parent_class(att)
if pclass is not None:
if pclass.get_global_identifier() == KnownClassGuids.NumericAttribute:
try:
val = float(value)
max_val = self.get_attribute_value(att, self.get_instance_by_global_identifier(KnownAttributeGuids.MaximumValue))
min_val = self.get_attribute_value(att, self.get_instance_by_global_identifier(KnownAttributeGuids.MinimumValue))
if (min_val is not None and val < min_val) or (max_val is not None and val > max_val):
return OmsResult(False, "parameter out of range: value")
except ValueError:
return OmsResult(False, "parameter type mismatch: expected int, got " + str(type(value)))
self.set_attribute_value_internal(inst, att, value)
return OmsResult.SUCCESS
def get_instance_by_key(self, key : InstanceKey):
pass
def get_instance_by_global_identifier(self, global_identifier : Guid):
pass
def get_instances(self, of_class : InstanceReference = None):
pass
def get_tenant_by_name(self, tenant_name : str) -> TenantReference:
pass
def get_related_instances(self, inst : InstanceReference, rel : InstanceReference) -> list[InstanceReference]:
pass
def get_related_instance(self, inst : InstanceReference, rel : InstanceReference) -> InstanceReference | None:
rels = self.get_related_instances(inst, rel)
if len(rels) == 0:
return None
return rels[0]
def assign_attribute(self, instance : InstanceReference, attribute : InstanceReference, value : str):
pass
def assign_relationship(self, instance : InstanceReference, relationship : InstanceReference, related_instances : InstanceReference|list):
pass
def get_instance_text(self, inst : InstanceReference) -> str:
# first see if we have a parent class with `Class.instance labeled by Executable returning Attribute`
pclasz = self.get_parent_class(inst)
if pclasz is not None:
rel = self.get_instance_by_global_identifier(KnownRelationshipGuids.Class__instances_labeled_by__Executable_returning_Attribute)
relinst = self.get_related_instance(pclasz, rel)
if relinst is not None:
text = "EXEC:" + str(relinst.get_instance_key()) # self.execute(relinst)
return text
# if all else fails, try getting the `Name` attribute
attr = self.get_instance_by_global_identifier(KnownAttributeGuids.Name)
text = self.get_attribute_value(inst, attr)
if text is None:
text = ""
return text
def _create_instance_of(self, class_inst : InstanceReference, global_identifier : Guid = None):
pass
def create_instance_of(self, class_inst : InstanceReference, global_identifier : Guid = None):
inst = self._create_instance_of(class_inst, global_identifier)
rel_Class__has__Instance = self.get_instance_by_global_identifier(KnownRelationshipGuids.Class__has__Instance)
if rel_Class__has__Instance is None:
return inst
rel_Instance__for__Class = self.get_instance_by_global_identifier(KnownRelationshipGuids.Instance__for__Class)
if rel_Instance__for__Class is None:
return inst
self.assign_relationship(class_inst, rel_Class__has__Instance, inst)
self.assign_relationship(inst, rel_Instance__for__Class, class_inst)
return inst
def set_user_password(self, user : InstanceReference, password : str):
ik_UserName = self.get_instance_by_global_identifier(KnownAttributeGuids.UserName)
ik_PasswordHash = self.get_instance_by_global_identifier(KnownAttributeGuids.PasswordHash)
ik_PasswordSalt = self.get_instance_by_global_identifier(KnownAttributeGuids.PasswordSalt)
username = self.get_attribute_value(user, self.get_instance_by_global_identifier(KnownAttributeGuids.UserName))
salt = Guid.create().strip()
passsalt = str(password + salt).encode("utf-8")
import hashlib
passhash = hashlib.sha512(passsalt).hexdigest()
self.assign_attribute(user, ik_UserName, username)
self.assign_attribute(user, ik_PasswordHash, passhash)
self.assign_attribute(user, ik_PasswordSalt, salt)
def create_user(self, username : str, password : str, global_identifier : Guid = None):
user = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.User), global_identifier)
if password is not None:
self.set_user_password(user, password)
def before_init(self):
pass
def _init(self):
ik_Class = self.create_class(1, 1, 'Class', KnownClassGuids.Class)
self.create_class(1, 2, 'Attribute', KnownClassGuids.Attribute)
ik_Relationship = self.create_class(1, 3, 'Relationship', KnownClassGuids.Relationship)
ik_TextAttribute = self.create_class(1, 4, 'Text Attribute', KnownClassGuids.TextAttribute)
ik_BooleanAttribute = self.create_class(1, 5, 'Boolean Attribute', KnownClassGuids.BooleanAttribute)
self.create_class(1, 6, 'Element', KnownClassGuids.Element)
ik_NumericAttribute = self.create_class(1, 20, 'Numeric Attribute', KnownClassGuids.NumericAttribute)
ik_RichTextAttribute = self.create_class(1, 2737, 'Rich Text Attribute', KnownClassGuids.RichTextAttribute)
att_Name = self.create_instance_of(ik_TextAttribute, KnownAttributeGuids.Name)
att_Value = self.create_instance_of(ik_TextAttribute, KnownAttributeGuids.Value)
att_Token = self.create_instance_of(ik_TextAttribute, KnownAttributeGuids.Token)
rel_Relationship__has_source__Class = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.Relationship), KnownRelationshipGuids.Relationship__has_source__Class)
rel_Relationship__has_destination__Class = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.Relationship), KnownRelationshipGuids.Relationship__has_destination__Class)
rel_Relationship__has_sibling__Relationship = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.Relationship), KnownRelationshipGuids.Relationship__has_sibling__Relationship)
ik_Singular = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.BooleanAttribute), KnownAttributeGuids.Singular)
ik_RelationshipType = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.RelationshipType)
ik_Instance = self.create_class(1, 17, "Instance", KnownClassGuids.Instance)
ik_User = self.create_class(1, 39, 'System User', KnownClassGuids.User)
ik_UserLogin = self.create_class(1, 4328, 'System Account Signon', KnownClassGuids.UserLogin)
ik_UserName = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.UserName)
self.assign_attribute(ik_UserName, self.get_instance_by_global_identifier(KnownAttributeGuids.Name), "User Name")
ik_PasswordHash = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.PasswordHash)
self.assign_attribute(ik_PasswordHash, self.get_instance_by_global_identifier(KnownAttributeGuids.Name), "Password Hash")
ik_PasswordSalt = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.PasswordSalt)
self.assign_attribute(ik_PasswordSalt, self.get_instance_by_global_identifier(KnownAttributeGuids.Name), "Password Salt")
superuser = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.User), KnownInstanceGuids.User.superuser)
self.assign_attribute(superuser, ik_UserName, "superuser")
self.assign_attribute(superuser, ik_PasswordHash, "0bdbeeecd24e93a0d84ff2946c519761d4db2c52d9449d2de5bf3b74a8bcdfbee9d72bb88121a63700d09554983e7f881021ecf493f83dec19e8f7e465529c34")
self.assign_attribute(superuser, ik_PasswordSalt, "5e28b86839ed4ca9838c112723aeaa27")
self.create_user("zq-configurator", "Florida407!", KnownInstanceGuids.User.zq_configurator)
self.create_user("zq-developer", "Florida407!", KnownInstanceGuids.User.zq_developer)
self.create_user("zq-environments", "Florida407!", KnownInstanceGuids.User.zq_environments)
self.create_user("zq-implementer", "Florida407!", KnownInstanceGuids.User.zq_implementer)
self.create_user("zq-support", "Florida407!", KnownInstanceGuids.User.zq_support)
self.assign_attribute(self.get_instance_by_key(InstanceKey(1, 2)), self.get_instance_by_key(InstanceKey(4, 1)), 'Attribute')
self.assign_attribute(self.get_instance_by_key(InstanceKey(1, 3)), self.get_instance_by_key(InstanceKey(4, 1)), 'Relationship')
self.assign_attribute(self.get_instance_by_key(InstanceKey(1, 4)), self.get_instance_by_key(InstanceKey(4, 1)), 'Text Attribute')
self.assign_attribute(self.get_instance_by_key(InstanceKey(4, 1)), self.get_instance_by_key(InstanceKey(4, 1)), 'Name')
self.assign_attribute(self.get_instance_by_key(InstanceKey(4, 2)), self.get_instance_by_key(InstanceKey(4, 1)), 'Value')
self.assign_attribute(self.get_instance_by_key(InstanceKey(4, 3)), self.get_instance_by_key(InstanceKey(4, 1)), 'Token')
ik_User_Login__for__User = self.create_relationship(ik_UserLogin, "for", ik_User, False, None, KnownRelationshipGuids.User_Login__has__User)
# self.create_relationship(ik_User, "has", ik_UserLogin, False, ik_User_Login__for__User, KnownRelationshipGuids.User__has__User_Login)
self.update_relationship(rel_Relationship__has_source__Class, ik_Relationship, "has source", ik_Class, True, None)
self.update_relationship(rel_Relationship__has_destination__Class, ik_Relationship, "has destination", ik_Class, True, None)
self.update_relationship(rel_Relationship__has_sibling__Relationship, ik_Relationship, "has sibling", ik_Relationship, True, None)
rel_Class__has__Instance = self.create_relationship(ik_Class, "has", ik_Instance, False, None, KnownRelationshipGuids.Class__has__Instance)
rel_Instance__for__Class = self.create_relationship(ik_Instance, "for", ik_Class, True, None, KnownRelationshipGuids.Instance__for__Class)
self.update_relationship(rel_Class__has__Instance, None, None, None, None, rel_Instance__for__Class)
self.update_relationship(rel_Instance__for__Class, None, None, None, None, rel_Class__has__Instance)
ik_MaximumLength = self.create_instance_of(ik_NumericAttribute, KnownAttributeGuids.MaximumLength)
self.set_attribute_value(ik_MaximumLength, att_Name, "Maximum Length")
ik_MinimumValue = self.create_instance_of(ik_NumericAttribute, KnownAttributeGuids.MinimumValue)
self.set_attribute_value(ik_MinimumValue, att_Name, "Minimum Value")
ik_MaximumValue = self.create_instance_of(ik_NumericAttribute, KnownAttributeGuids.MaximumValue)
self.set_attribute_value(ik_MaximumValue, att_Name, "Maximum Value")
self.set_attribute_value(ik_Class, att_Name, "Class")
self.update_class_instances()
def update_relationship(self, relationship : InstanceReference, src_class : InstanceReference, type : str, dst_class : InstanceReference, singular: bool, sibling_relationship : InstanceReference):
if src_class is not None:
self.assign_relationship(relationship, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_source__Class), src_class)
if type is not None:
self.assign_attribute(relationship, self.get_instance_by_global_identifier(KnownAttributeGuids.RelationshipType), type)
if dst_class is not None:
self.assign_relationship(relationship, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_destination__Class), dst_class)
if singular is not None:
self.assign_attribute(relationship, self.get_instance_by_global_identifier(KnownAttributeGuids.Singular), singular)
if sibling_relationship is not None:
self.assign_relationship(relationship, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_sibling__Relationship), sibling_relationship)
def update_class_instances(self):
ik_Class = self.get_instance_by_global_identifier(KnownClassGuids.Class)
rel_Class__has__Instance = self.get_instance_by_global_identifier(KnownRelationshipGuids.Class__has__Instance)
rel_Instance__for__Class = self.get_instance_by_global_identifier(KnownRelationshipGuids.Instance__for__Class)
insts = self.get_instances()
for inst in insts:
clasz = self.get_instance_by_key(InstanceKey(1, inst.get_instance_key().get_class_index() ))
self.assign_relationship(clasz, rel_Class__has__Instance, inst)
self.assign_relationship(inst, rel_Instance__for__Class, clasz)
def after_init(self):
pass
def init(self):
self.before_init()
self._init()
self.after_init()

View File

@ -0,0 +1,9 @@
class OmsResult:
def __init__(self, success : bool, message : str):
self.success = success
self.message = message
OmsResult.SUCCESS = OmsResult(True, "the operation completed successfully")

View File

@ -0,0 +1,2 @@
from .Oms import Oms
from .OmsResult import OmsResult

View File

@ -1,4 +1,4 @@
from .Oms import Oms
from ..Oms import Oms
class DatabaseOms(Oms):
pass

View File

@ -1,7 +1,7 @@
from .Oms import Oms
from .DatabaseOms import DatabaseOms
from ..DatabaseOms import DatabaseOms
from ..core import InstanceKey, InstanceReference, TenantReference
from ...core import InstanceKey, InstanceReference, TenantReference
import mysql.connector
@ -118,6 +118,9 @@ class MySQLDatabaseOms(DatabaseOms):
return None
def get_related_instances(self, inst : InstanceReference, rel : InstanceReference) -> list[InstanceReference]:
pass
def get_tenant_by_name(self, tenant_name : str) -> TenantReference:
mycur = self.db.cursor()

View File

@ -0,0 +1,260 @@
from ..DatabaseOms import DatabaseOms
from ....core.InstanceKey import InstanceKey
from ....core.InstanceReference import InstanceReference
import sqlite3
from framework import Guid
from ....definitions import KnownClassGuids, KnownInstanceGuids, KnownAttributeGuids, KnownRelationshipGuids
class SQLiteDatabaseOms (DatabaseOms):
def __init__(self):
self.conn = None
self.__is_open = False
def open(self, filename : str):
"""
Opens the SQLite database with the given filename.
"""
self.conn = sqlite3.Connection(filename)
self.__is_open = True
def is_open(self):
return self.__is_open
def get_next_instance_index(self, class_inst : InstanceReference):
cursor = self.conn.execute("SELECT MAX(inst_id) + 1 FROM instances WHERE class_id = ?", [ class_inst.get_instance_key().get_instance_index() ])
result = cursor.fetchone()[0]
if result is None:
result = 1
return result
def _create_instance_of(self, class_inst : InstanceReference, global_identifier : Guid = None):
if global_identifier is None:
global_identifier = Guid.create()
next_iid = self.get_next_instance_index(class_inst)
result = self.conn.execute("INSERT INTO instances (class_id, inst_id, global_identifier, effective_date) VALUES (?, ?, ?, CURRENT_TIMESTAMP)", [ class_inst.get_instance_key().get_instance_index(), next_iid, global_identifier.strip() ])
lastrowid = result.lastrowid
# self.conn.execute("INSERT INTO attributes (src_inst_id, att_inst_id, att_value, effective_date) VALUES (?, ?, ?, CURRENT_TIMESTAMP)", [ result.lastrowid, 5, name ])
self.conn.commit()
cursor = self.conn.execute("SELECT * FROM instances WHERE id = ?", [ lastrowid ])
results = cursor.fetchall()
result = results[0]
return self.get_instance_from_database(result)
def create_class(self, class_id : int, inst_id : int, name : str, global_identifier : Guid):
print ("create class : " + str(class_id) + "$" + str(inst_id) + " [" + name + "] " + str(global_identifier) + ";")
result = self.conn.execute("INSERT INTO instances (class_id, inst_id, global_identifier, effective_date) VALUES (?, ?, ?, CURRENT_TIMESTAMP)", [ class_id, inst_id, global_identifier.strip() ])
lastrowid = result.lastrowid
print ("lastrowid: " + str(result.lastrowid))
self.conn.execute("INSERT INTO attributes (src_inst_id, att_inst_id, att_value, effective_date) VALUES (?, ?, ?, CURRENT_TIMESTAMP)", [ result.lastrowid, 5, name ])
self.conn.commit()
cursor = self.conn.execute("SELECT * FROM instances WHERE id = ?", [ lastrowid ])
results = cursor.fetchall()
result = results[0]
return self.get_instance_from_database(result)
def get_attributes(self, instance : InstanceReference):
if instance is None:
return [ ]
cursor = self.conn.execute("SELECT DISTINCT att_inst_id FROM attributes WHERE src_inst_id = ? AND effective_date <= CURRENT_TIMESTAMP ORDER BY effective_date DESC", [ instance.dbid ])
results = cursor.fetchall()
retval = [ ]
for result in results:
retval.append(self.get_instance_by_dbid(result[0]))
return retval
def get_relationships(self, instance : InstanceReference):
if instance is None:
return [ ]
cursor = self.conn.execute("SELECT DISTINCT rel_inst_id FROM relationships WHERE src_inst_id = ? AND effective_date <= CURRENT_TIMESTAMP ORDER BY effective_date DESC", [ instance.dbid ])
results = cursor.fetchall()
retval = [ ]
for result in results:
retval.append(self.get_instance_by_dbid(result[0]))
return retval
def get_related_instances(self, instance : InstanceReference, relationship : InstanceReference):
if instance is None:
return [ ]
if relationship is None:
return [ ]
cursor = self.conn.execute("SELECT dst_inst_id, remove_flag FROM relationships WHERE src_inst_id = ? AND rel_inst_id = ? AND effective_date <= CURRENT_TIMESTAMP ORDER BY effective_date DESC", [ instance.dbid, relationship.dbid ])
results = cursor.fetchall()
retval_ids = [ ]
retval = [ ]
for result in results:
if result[0] in retval_ids:
if result[1] == 1:
# remove flag
retval_ids.remove(result[0])
else:
retval_ids.append(result[0])
for id in retval_ids:
retval.append(self.get_instance_by_dbid(id))
return retval
def assign_attribute(self, instance : InstanceReference, attribute : InstanceReference, value : str):
self.conn.execute("INSERT INTO attributes (src_inst_id, att_inst_id, att_value, effective_date) VALUES (?, ?, ?, CURRENT_TIMESTAMP)", [ instance.get_dbid(), attribute.get_dbid(), value ])
self.conn.commit()
def assign_relationship(self, instance : InstanceReference, relationship : InstanceReference, related_instances : InstanceReference|list):
if relationship is None:
raise ValueError("relationship for assign_relationship is None")
if related_instances is None:
raise ValueError("related_instances must not be None")
if isinstance(related_instances, InstanceReference):
related_instances = [ related_instances ]
if isinstance(related_instances, list):
for inst in related_instances:
if not inst is None:
self.conn.execute("INSERT INTO relationships (src_inst_id, rel_inst_id, dst_inst_id, remove_flag, effective_date) VALUES (?, ?, ?, 0, CURRENT_TIMESTAMP)", [ instance.get_dbid(), relationship.get_dbid(), inst.get_dbid() ])
else:
print("error: target inst for assign_relationship is None")
else:
print("related_instances must be either InstanceReference or list, was " + str(type(inst)))
return
self.conn.commit()
def get_instance_by_dbid(self, dbid : int) -> InstanceReference:
if self.conn is None:
return None
cursor = self.conn.execute("SELECT * FROM instances WHERE id = ? AND (effective_date IS NULL OR effective_date <= CURRENT_TIMESTAMP)", [ dbid ])
results = cursor.fetchall()
if len(results) > 0:
return self.get_instance_from_database(results[0])
return None
def get_instance_by_key(self, key : InstanceKey) -> InstanceReference:
if self.conn is None:
return None
qry = "SELECT * FROM instances WHERE class_id = " + str(key.get_class_index()) + " AND inst_id = " + str(key.get_instance_index()) + " AND (effective_date IS NULL OR effective_date <= CURRENT_TIMESTAMP)"
result = self.conn.execute(qry)
results = result.fetchall()
if len(results) > 0:
return self.get_instance_from_database(results[0])
return None
# retval = [ ]
# for res in results:
# retval.append(InstanceReference(int(res[0]), InstanceKey(int(res[1]), int(res[2])), res[3]))
# if len(retval) == 1:
# return retval[0]
# elif len(retval) == 0:
# return None
# return retval
def get_attribute_value_internal(self, inst : InstanceReference, att : InstanceReference, default_value = None):
if inst is None or att is None:
return None
cursor = self.conn.execute("SELECT att_value FROM attributes WHERE src_inst_id = " + str(inst.dbid) + " AND att_inst_id = " + str(att.dbid) + " AND effective_date <= CURRENT_TIMESTAMP ORDER BY effective_date DESC, id DESC")
results = cursor.fetchall()
if (len(results) > 0):
return results[0][0]
return None
def set_attribute_value_internal(self, inst : InstanceReference, att : InstanceReference, value):
cursor = self.conn.execute("INSERT INTO attributes (src_inst_id, att_inst_id, att_value, effective_date) VALUES (?, ?, ?, CURRENT_TIMESTAMP)", [inst.dbid, att.dbid, value])
self.conn.commit()
def before_init(self):
self.conn.execute("DROP TABLE IF EXISTS instances")
self.conn.execute("DROP TABLE IF EXISTS attributes")
self.conn.execute("DROP TABLE IF EXISTS relationships")
self.conn.execute("DROP TABLE IF EXISTS relationship_instances")
self.conn.execute("CREATE TABLE instances (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, class_id INT, inst_id INT, global_identifier CHAR(32), effective_date DATETIME)")
self.conn.execute("CREATE TABLE attributes (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, src_inst_id INTEGER NOT NULL, att_inst_id INTEGER NOT NULL, att_value TEXT, effective_date DATETIME)")
# self.conn.execute("CREATE TABLE relationships (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, src_inst_id INTEGER NOT NULL, rel_inst_id INTEGER NOT NULL, effective_date DATETIME)")
# self.conn.execute("CREATE TABLE relationship_instances (rel_id INTEGER NOT NULL, inst_id INTEGER NOT NULL, remove_flag INTEGER NOT NULL, effective_date DATETIME)")
self.conn.execute("CREATE TABLE relationships (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, src_inst_id INTEGER NOT NULL, rel_inst_id INTEGER NOT NULL, dst_inst_id INTEGER NOT NULL, remove_flag INTEGER NOT NULL, effective_date DATETIME)")
def after_init(self):
self.conn.commit()
def get_instances(self, of_class : InstanceReference = None):
if self.conn is None:
return None
if of_class is not None:
cursor = self.conn.execute("SELECT * FROM instances WHERE class_id = ?", [ of_class.get_instance_key().get_instance_index() ])
results = cursor.fetchall()
insts = [ ]
for result in results:
inst = self.get_instance_from_database(result)
insts.append(inst)
return insts
else:
cursor = self.conn.execute("SELECT * FROM instances")
results = cursor.fetchall()
insts = [ ]
for result in results:
inst = self.get_instance_from_database(result)
insts.append(inst)
return insts
def get_instance_from_database(self, result):
return InstanceReference(int(result[0]), InstanceKey(int(result[1]), int(result[2])), Guid.parse(result[3]))
def get_instance_by_global_identifier(self, global_identifier : Guid):
if self.conn is None:
return None
cursor = self.conn.execute("SELECT * FROM instances WHERE global_identifier = ?", [ global_identifier.strip() ])
results = cursor.fetchall()
if len(results) > 0:
return self.get_instance_from_database(results[0])
return None
def close(self):
self.conn.close()
self.__is_open = False

View File

@ -0,0 +1 @@
from .SQLiteDatabaseOms import SQLiteDatabaseOms

View File

@ -0,0 +1,13 @@
from ..Oms import Oms
class MemoryOms (Oms):
def __init__(self):
pass
def get_tenant_name(self):
return "super"
def load_from_path(self, path):
pass

View File

@ -0,0 +1 @@
from .MemoryOms import MemoryOms

View File

@ -0,0 +1,23 @@
class AssetLocation:
pass
class LocalAssetLocation(AssetLocation):
def __init__(self):
self.path = None
def __repr__(self):
return "local:" + self.path
class RemoteAssetLocation(AssetLocation):
def __init__(self):
self.path = None
def __repr__(self):
return "remote:" + self.path

View File

@ -0,0 +1,7 @@
class PathMapping:
def __init__(self, source_pattern : str, destination_path : str):
self.source_pattern = source_pattern
self.destination_path = destination_path

View File

@ -1,21 +1,34 @@
from .WebControl import WebControl
from .ui.WebControl import WebControl
from .WebStyleSheet import WebStyleSheet
from .XmlTag import XmlTag
from .xml import XmlTag
class WebPage (WebControl):
def __init__(self):
WebControl.__init__(self, 'html')
self.__initialized = False
self.__title = None
self.__body = XmlTag('body')
self.__head = XmlTag('head')
self.__style_sheet = WebStyleSheet()
self.add(self.__head)
self.__head.add(self.__style_sheet)
self.add(self.__body)
def initialize(self):
if self.__initialized is True:
return False
self.on_initializing()
self.__initialized = True
return True
def on_initializing(self):
pass
def create_from_json(self, json):
if "components" in json:
for component in json["components"]:
@ -49,6 +62,8 @@ class WebPage (WebControl):
def render_before_html(self):
self.initialize()
title = self.get_title()
if title is None:
title = ""

View File

@ -5,10 +5,12 @@ from urllib.parse import parse_qsl, urlparse
import json
from ..oms import Oms
from ..web.AssetLocation import LocalAssetLocation, RemoteAssetLocation
class WebRequestHandler(BaseHTTPRequestHandler):
def __init__(self, request, client_address, server):
BaseHTTPRequestHandler.__init__(self, request, client_address, server)
self.__oms = server._oms
@cached_property
def url(self):
@ -35,23 +37,29 @@ class WebRequestHandler(BaseHTTPRequestHandler):
self.send_response(302, "Found")
self.send_header("Location", url)
self.end_headers()
self.close_connection()
def respond_with_content(self, response_code, response_text, content_type, content):
def respond_with_content(self, response_code, response_text, content_type, content, headers = None):
self.send_response(response_code, response_text)
self.send_header("Content-Type", content_type)
self.send_header("Content-Length", len(content))
if headers is not None:
for (key, value) in headers:
self.send_header(key, value)
self.end_headers()
self.wfile.write(content.encode("utf-8"))
def get_oms(self) -> Oms:
from ..oms import MySQLDatabaseOms
# from ..oms import MySQLDatabaseOms
from ..oms.memory import MemoryOms
if not hasattr(self, "__oms"):
self.__oms = None
if self.__oms is None:
self.__oms = MySQLDatabaseOms("localhost", 13306, "mocha_user", "9Q5eLsKfL5AciM4U", "mocha_test")
# self.__oms = MySQLDatabaseOms("localhost", 13306, "mocha_user", "9Q5eLsKfL5AciM4U", "mocha_test")
self.__oms = MemoryOms()
return self.__oms
@ -62,23 +70,70 @@ class WebRequestHandler(BaseHTTPRequestHandler):
path = self.url.path.split('/')
path = path[1:]
mapping = self.server._server.find_path_mapping(path)
if mapping is not None:
self.respond_with_content(200, "OK", mapping.content_type, mapping.content)
return
if (len(path) == 1 and path[0] == ""):
self.respond_with_redirect("/" + default_tenant_name)
return
print(path)
if (len(path) > 0):
tenant_name = path[0]
if len(path) == 1:
self.respond_with_redirect("/madi/authgwy/" + tenant_name + "/login.htmld")
return
if path[0] == "robots.txt":
self.respond_with_content(200, "OK", "text/plain", """User-agent: *
Disallow: /
""")
return
else:
self.respond_with_redirect("/madi/authgwy/" + tenant_name + "/login.htmld")
return
if len(path) > 1:
if tenant_name == "madi":
authgwy = path[1]
if authgwy == "authgwy":
if authgwy == "asset":
if len(path) > 4:
module = path[2]
version = path[3]
assetPath = "/".join(path[4:])
print("module: " + module)
print("version: " + version)
print("assetPath: " + assetPath)
for assetLoc in self.server._server.assets:
if isinstance(assetLoc, LocalAssetLocation):
physicalPath = assetLoc.path + "/" + module + "/" + version + "/" + assetPath
print("asset is local: " + physicalPath)
elif isinstance(assetLoc, RemoteAssetLocation):
remotePath = assetLoc.path + "/" + module + "/" + version + "/" + assetPath
print("asset is remote: " + remotePath)
import os
if os.path.exists(physicalPath):
file = open(physicalPath, "r")
content = file.read()
self.respond_with_content(200, "OK", "text/css", content, [ ( "Content-Encoding", "UTF-8" )])
return
self.respond_with_content(404, "Not Found", "text/html", "<h1>Not Found</h1><p>The requested resource is not available on this server.</p>")
return
elif authgwy == "authgwy":
if len(path) == 4:
tenant_name = path[2]
file_name = path[3]
@ -90,8 +145,11 @@ class WebRequestHandler(BaseHTTPRequestHandler):
print(tenant.get_name())
if file_name == "login.htmld":
from .pages import LoginWebPage
from .ui.pages import LoginWebPage
page = LoginWebPage()
page.set_oms(self.get_oms())
self.respond_with_content(200, "OK", "application/xhtml+xml", page.render_html())
return
elif file_name == "tenant-config.xml":
@ -116,6 +174,8 @@ class WebRequestHandler(BaseHTTPRequestHandler):
if jj["result"] == "failure" and jj["remedy"] == "login":
self.respond_with_login_page(tenant_name)
return
else:
print(jj)
self.send_response(200)
self.send_header("Content-Type", "application/json")
@ -216,16 +276,22 @@ class WebRequestHandler(BaseHTTPRequestHandler):
loginPage = path[3]
else:
# error out
return
return {
"result": "error",
"message": "path len not eq 4",
"path": path
}
else:
# error out
return
return {
"result": "error",
"message": "not found 'authgwy'"
}
from ..core import InstanceKey
from ..oms import MySQLDatabaseOms
oms = MySQLDatabaseOms("localhost", 13306, "mocha_user", "9Q5eLsKfL5AciM4U", "mocha_test")
oms = self.get_oms()
if len(path) > 3:
if path[1] == "api":

View File

@ -1,4 +1,4 @@
from .XmlTag import XmlTag
from .xml import XmlTag
class WebScript (XmlTag):

View File

@ -0,0 +1,42 @@
from . import WebRequestHandler, PathMapping
from ..oms import Oms
class WebServer():
def __init__(self, endpoint, oms : Oms):
"""
Initializes a new instance of the Mocha User Interface Service.
`endpoint` is a tuple consisting of (str address, int port)
"""
self.__tup = endpoint
self._oms = oms
self.path_mappings = [ ]
self.assets = [ ]
def match_path_pattern(self, source_pattern, path_format):
vars = [ ]
if source_pattern == path_format:
return (True, vars)
# TODO: add intelligent path parsing from PHP/Phast
# from framework.web import WebPathParser... (e.g.)
return (False, vars)
def find_path_mapping(self, path_format : str):
for mapping in self.path_mappings:
(success, vars) = self.match_path_pattern(mapping.source_pattern, path_format)
if success:
for varname in vars:
mapping.set_property_value(varname, vars[varname])
return mapping
return None
def serve_forever(self):
from http.server import HTTPServer
server = HTTPServer(self.__tup, WebRequestHandler)
server._oms = self._oms
server._server = self
server.serve_forever()

View File

@ -1,4 +1,4 @@
from .XmlTag import XmlTag
from .xml import XmlTag
class WebStyleSheet (XmlTag):

View File

@ -0,0 +1,12 @@
from .xml import XmlTag
class WebStyleSheetReference (XmlTag):
def __init__(self, path):
XmlTag.__init__(self, 'link')
self.add_attribute("rel", "stylesheet")
self.add_attribute("type", "text/css")
self.add_attribute("href", path)
def has_content_or_controls(self):
return False

View File

@ -0,0 +1,7 @@
from .PathMapping import PathMapping
from .WebPage import WebPage
from .WebRequestHandler import WebRequestHandler
from .WebScript import WebScript
from .WebServer import WebServer
from .WebStyleSheet import WebStyleSheet
from .WebStyleSheetReference import WebStyleSheetReference

View File

@ -0,0 +1,77 @@
from ...oms.memory import MemoryOms
from ..WebServer import WebServer
from ..AssetLocation import LocalAssetLocation, RemoteAssetLocation
from ..PathMapping import PathMapping
class ServerManager:
def __init__(self):
self._servers = [ ]
def add_server_config(self, filename):
import yaml
with open(filename, 'r') as file:
content = yaml.safe_load_all(file)
for doc in content:
for d in doc:
for s in d["server"]:
if not "port" in s:
print("error: 'port' not defined for server definition")
return
port = s["port"]
print("[ INFO ]: running server on port " + str(port))
oms = MemoryOms()
svr = WebServer(("127.0.0.1", port), oms)
if "pathMappings" in s:
pathMappings = s["pathMappings"]
for pathMapping in pathMappings:
svr.path_mappings.append(PathMapping(pathMapping["source"], pathMapping["destination"]))
print("[ INFO ]: map path '" + pathMapping["destination"] + "' to file path '" + pathMapping["source"] + "'")
if "assets" in s:
for asset in s["assets"]:
theAsset = None
if not "type" in asset:
print("error: asset location definition does not contain 'type'")
continue
elif not "path" in asset:
print("error: asset location definition does not contain 'path'")
continue
if asset["type"] == "local":
theAsset = LocalAssetLocation()
elif asset["type"] == "remote":
theAsset = RemoteAssetLocation()
if not theAsset is None:
theAsset.path = asset["path"]
svr.assets.append(theAsset)
else:
print("error: unsupported asset type " + str(asset["type"]))
print ("loaded assets")
print(svr.assets)
if "tenants" in s:
tenants = s["tenants"]
else:
print("warning: no tenants defined in server configuration")
self._servers.append(svr)
def start(self):
import threading
for server in self._servers:
t = threading.Thread(target = self._serve, args = [ server ])
t.start()
def _serve(self, server):
server.serve_forever()

View File

@ -0,0 +1 @@
from .ServerManager import ServerManager

View File

@ -1,4 +1,4 @@
from .XmlTag import XmlTag
from ..xml import XmlTag
class WebControl (XmlTag):

View File

@ -1,19 +1,31 @@
from ..WebScript import WebScript
from ..WebPage import WebPage
from ...WebScript import WebScript
from ...WebPage import WebPage
from ....oms import Oms
from ...WebStyleSheetReference import WebStyleSheetReference
class BaseWebPage (WebPage):
def __init__(self):
WebPage.__init__(self)
self._oms = None
def on_initializing(self):
self.get_style_sheet().add_rule('table', { 'width': '100%' })
self.get_head().add(self.get_client_config_script())
self.get_head().add(WebStyleSheetReference("/madi/asset/ui-html/2024.03.09/css/main.css"))
def get_oms(self):
return self._oms
def set_oms(self, oms : Oms):
self._oms = oms
def get_client_config_script(self):
return WebScript("text/javascript", content="""
// Add properties to mocha
window.mocha = window.mocha || {};
mocha.tenant = 'cityoforlando3';
mocha.tenant = '""" + self.get_oms().get_tenant_name() + """';
mocha.clientOrigin = 'https://wd5-impl.workday.com';
mocha.language = 'en_US';
mocha.clientVersion = '0';

View File

@ -0,0 +1,3 @@
from .BaseWebPage import BaseWebPage
from .HomeWebPage import HomeWebPage
from .LoginWebPage import LoginWebPage

View File

@ -0,0 +1,3 @@
from .XmlAttribute import XmlAttribute
from .XmlTag import XmlTag
from .XmlTagStyles import XmlTagStyles

View File

@ -1,10 +0,0 @@
from mocha.web.WebServer import WebServer
if __name__ == "__main__":
port = 8081
print("Mocha User Interface Service - running on port", port)
server = WebServer(("127.0.0.1", port))
server.serve_forever()

View File

@ -1,35 +0,0 @@
from ..core import *
from ..oms import Oms
class MemoryOms(Oms):
def __init__(self):
self.__current_tenant = None
self.__instances = dict()
self.__tenants = dict()
def get_instance_by_key(self, key : InstanceKey):
return self.__instances[key.to_tuple()]
# def get_instance_by_global_identifier(self, global_identifier : Guid):
def create_tenant(self, tenant_name : str):
if tenant_name in self.__tenants:
raise NameError("tenant with specified name already exists")
self.__tenants[tenant_name] = TenantReference(tenant_name, None)
def select_tenant(self, tenant : TenantReference):
self.__current_tenant = tenant
def release_tenant(self):
self.__current_tenant = None
def get_current_tenant(self):
return self.__current_tenant
def get_tenant_by_name(self, tenant_name : str):
if tenant_name in self.__tenants:
return self.__tenants[tenant_name]
return None

View File

@ -1,14 +0,0 @@
from ..core import InstanceKey, InstanceReference, TenantReference
class Oms:
def __init__(self):
pass
def get_instance_by_key(self, key : InstanceKey):
pass
def get_instances(self, of_class : InstanceReference = None):
pass
def get_tenant_by_name(self, tenant_name : str) -> TenantReference:
pass

View File

@ -1,4 +0,0 @@
from .Oms import Oms
from .DatabaseOms import DatabaseOms
from .MemoryOms import MemoryOms
from .MySQLDatabaseOms import MySQLDatabaseOms

View File

@ -1,12 +0,0 @@
from .WebRequestHandler import WebRequestHandler
class WebServer():
def __init__(self, tup):
self.__tup = tup
def serve_forever(self):
from http.server import HTTPServer
server = HTTPServer(self.__tup, WebRequestHandler)
server.serve_forever()

View File

@ -1,2 +0,0 @@
from .LoginWebPage import LoginWebPage
from .HomeWebPage import HomeWebPage