modelverse.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. import urllib
  2. import urllib2
  3. import json
  4. import random
  5. from urllib2 import URLError
  6. import sys
  7. # Bind to the compiler
  8. sys.path.append("../interface/HUTN")
  9. from hutn_compiler.compiler import main as do_compile
  10. # Helper functions and configuration: do not use yourself!
  11. taskname = random.random()
  12. address = None
  13. last_output = None
  14. mode = 0
  15. def _input(value):
  16. # Ugly json encoding of primitives
  17. if isinstance(value, type([])):
  18. value = json.dumps(value)
  19. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "data": value, "taskname": taskname}))).read()
  20. else:
  21. value = json.dumps(value)
  22. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "value": value, "taskname": taskname}))).read()
  23. def _input_raw(value, taskname):
  24. # Ugly json encoding of primitives
  25. urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "set_input", "value": value, "taskname": taskname}))).read()
  26. def _compile_AL(code):
  27. # Compile an action language file and send the compiled code
  28. code_fragments = code.split("\n")
  29. code_fragments = [i for i in code_fragments if i.strip() != ""]
  30. code_fragments = [i.replace(" ", "\t") for i in code_fragments]
  31. initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
  32. code_fragments = [i[initial_tabs:] for i in code_fragments]
  33. code_fragments.append("")
  34. code = "\n".join(code_fragments)
  35. with open("__constraint.alc", "w") as f:
  36. f.write(code)
  37. f.flush()
  38. _input(do_compile("__constraint.alc", "../interface/HUTN/grammars/actionlanguage.g", "CS"))
  39. def _compile_model(code):
  40. # Compile a model and send the compiled graph
  41. # First change multiple spaces to a tab
  42. code_fragments = code.split("\n")
  43. code_fragments = [i for i in code_fragments if i.strip() != ""]
  44. code_fragments = [i.replace(" ", "\t") for i in code_fragments]
  45. initial_tabs = min([len(i) - len(i.lstrip("\t")) for i in code_fragments])
  46. code_fragments = [i[initial_tabs:] for i in code_fragments]
  47. code_fragments.append("")
  48. code = "\n".join(code_fragments)
  49. with open("__model.mvc", "w") as f:
  50. f.write(code)
  51. f.flush()
  52. _input(do_compile("__model.mvc", "../interface/HUTN/grammars/modelling.g", "M") + ["exit"])
  53. def _output():
  54. try:
  55. global last_output
  56. last_output = json.loads(urllib2.urlopen(urllib2.Request(address, urllib.urlencode({"op": "get_output", "taskname": taskname}))).read())
  57. return last_output
  58. except:
  59. raise UnknownError()
  60. def _last_output():
  61. return last_output
  62. def _consume_to_end():
  63. while (_output() not in ["Ready for command...", "Please give your command."]):
  64. pass
  65. # Exceptions
  66. class ModelverseException(Exception):
  67. pass
  68. class UnknownError(ModelverseException):
  69. pass
  70. class UnknownIdentifier(ModelverseException):
  71. pass
  72. class UnknownType(ModelverseException):
  73. pass
  74. class UnsupportedValue(ModelverseException):
  75. pass
  76. class CompilationError(ModelverseException):
  77. pass
  78. class NoSuchAttribute(ModelverseException):
  79. pass
  80. class UnknownModel(ModelverseException):
  81. pass
  82. class ConnectionError(ModelverseException):
  83. pass
  84. class ModelExists(ModelverseException):
  85. pass
  86. class PermissionDenied(ModelverseException):
  87. pass
  88. class InvalidMode(ModelverseException):
  89. pass
  90. # Main MvC operations
  91. def init(address_param="http://localhost:8001"):
  92. """Starts up the connection to the Modelverse."""
  93. # return None
  94. # raises ConnectionError
  95. # raises UnknownError
  96. # raises InvalidMode
  97. global mode
  98. if mode != 0:
  99. raise InvalidMode()
  100. global address
  101. address = address_param
  102. try:
  103. _input_raw('"%s"' % taskname, "task_manager")
  104. mode = 1
  105. except URLError as e:
  106. raise ConnectionError(e.reason)
  107. def login(username, password):
  108. """Log in an existing user."""
  109. # return None
  110. # raises UnknownError
  111. # raises PermissionDenied
  112. global mode
  113. if mode != 1:
  114. raise InvalidMode()
  115. _input(username)
  116. _input(password)
  117. _consume_to_end()
  118. mode = 2
  119. def register(username, password):
  120. """Register a new user."""
  121. # return None
  122. # raises UnknownError
  123. # raises UserExists
  124. global mode
  125. if mode != 1:
  126. raise InvalidMode()
  127. _input(username)
  128. _input(password)
  129. _input(password)
  130. _consume_to_end()
  131. mode = 2
  132. def model_add(model_name, metamodel_name, model_code):
  133. """Instantiate a new model."""
  134. # return None
  135. # raises UnknownModel
  136. # raises ModelExists
  137. # raises UnknownError
  138. # raises PermissionDenied
  139. # raises CompilationError
  140. if mode != 2:
  141. raise InvalidMode()
  142. _input("model_add")
  143. _output()
  144. _output()
  145. _input(metamodel_name)
  146. if _output() == "Model name?":
  147. _input(model_name)
  148. if _output() == "Waiting for model constructors...":
  149. try:
  150. _compile_model(model_code)
  151. except Exception:
  152. raise CompilationError()
  153. _consume_to_end()
  154. else:
  155. _consume_to_end()
  156. raise ModelExists()
  157. elif _last_output() == "Could not find type model!":
  158. _consume_to_end()
  159. raise UnknownModel()
  160. elif _last_output() == "Permission denied":
  161. _consume_to_end()
  162. raise PermissionDenied()
  163. def model_modify(model_name):
  164. """Modify an existing model."""
  165. # return is_write
  166. # raises UnknownModel
  167. # raises PermissionDenied
  168. # raises UnknownError
  169. global mode
  170. if mode != 2:
  171. raise InvalidMode()
  172. _input("model_modify")
  173. _output()
  174. _input(model_name)
  175. if _output() == "Permission denied":
  176. _consume_to_end()
  177. raise PermissionDenied()
  178. elif _last_output() == "Could not find model!":
  179. _consume_to_end()
  180. raise UnknownModel()
  181. elif _last_output() == "Model loaded, ready for commands!":
  182. mode = 3
  183. if ("r/w" in _output()):
  184. write = True
  185. else:
  186. write = False
  187. _consume_to_end()
  188. return write
  189. else:
  190. _consume_to_end()
  191. raise UnknownException()
  192. def model_list():
  193. """List all models."""
  194. # return [(model1, metamodel1), (model2, metamodel2), ...]
  195. # raises UnknownError
  196. if mode != 2:
  197. raise InvalidMode()
  198. _input("model_list")
  199. lst = []
  200. while (_output() != "Ready for command..."):
  201. v = _last_output()
  202. m, mm = v.split(":")
  203. m = m.strip()
  204. mm = mm.strip()
  205. lst.append((m, mm))
  206. return lst
  207. def model_list_full():
  208. """List full information on all models."""
  209. # return [(model1, metamodel1, owner1, group1, permissions1), (model2, metamodel2, owner2, group2, permissions2), ...]
  210. # raises UnknownError
  211. if mode != 2:
  212. raise InvalidMode()
  213. _input("model_list_full")
  214. lst = []
  215. while (_output() != "Ready for command..."):
  216. v = _last_output()
  217. m, mm = v.split(":")
  218. m = m.strip()
  219. mm = mm.strip()
  220. perm, own, grp, m = m.split(" ")
  221. lst.append((m, mm, own, grp, perm))
  222. return lst
  223. def model_overwrite(model_name, new_model):
  224. """Upload a new model and overwrite an existing model."""
  225. # return None
  226. # raises UnknownModel
  227. # raises PermissionDenied
  228. # raises CompilationError
  229. # raises UnknownError
  230. if mode != 2:
  231. raise InvalidMode()
  232. _input("model_overwrite")
  233. _input(model_name)
  234. _compile_model(new_model)
  235. def user_logout():
  236. """Log out the current user. A new login will be required afterwards."""
  237. # return None
  238. # raises UnknownException
  239. global mode
  240. if mode != 2:
  241. raise InvalidMode()
  242. _input("exit")
  243. mode = 1
  244. def user_delete():
  245. """Removes the current user. A new login will be required afterwards."""
  246. # return None
  247. # raises UnknownException
  248. global mode
  249. if mode != 2:
  250. raise InvalidMode()
  251. _input("self-destruct")
  252. mode = 1
  253. # Actual operations on the model
  254. def element_list():
  255. """Return a list of all IDs and the type of the element"""
  256. # return [(name1, type1), (name2, type2), ...]
  257. # raises UnknownError
  258. if mode != 3:
  259. raise InvalidMode()
  260. _input("list")
  261. lst = []
  262. _output()
  263. while (_output() != "Please give your command."):
  264. v = _last_output()
  265. m, mm = v.split(":")
  266. m = m.strip()
  267. mm = mm.strip()
  268. lst.append((m, mm))
  269. return lst
  270. def types():
  271. """Return a list of all types usable in the model"""
  272. # return [type1, type2, ...]
  273. # raises UnknownError
  274. if mode != 3:
  275. raise InvalidMode()
  276. _input("types")
  277. _output()
  278. lst = []
  279. while (_output() != "Please give your command."):
  280. v = _last_output()
  281. m, mm = v.split(":")
  282. m = m.strip()
  283. lst.append(m)
  284. return lst
  285. def read(ID):
  286. """Return a tuple of information on the element: its type and source/target (None if not an edge)"""
  287. # return (type, (source, target))
  288. # raises UnknownError
  289. # raises UnknownIdentifier
  290. if mode != 3:
  291. raise InvalidMode()
  292. _input("read")
  293. _output()
  294. _input(ID)
  295. _output()
  296. if _last_output() == "Unknown element; aborting":
  297. _consume_to_end()
  298. raise UnknownIdentifier()
  299. else:
  300. t = _output().split(":")[1].strip()
  301. if (not _output().startswith("Source:")):
  302. rval = (t, None)
  303. else:
  304. src = _last_output().split(":")[1].strip()
  305. trg = _output().split(":")[1].strip()
  306. rval = (t, (src, trg))
  307. while (_output() != "Please give your command."):
  308. pass
  309. return rval
  310. def read_attrs(ID):
  311. """Return a dictionary of attribute value pairs"""
  312. # return {attr1: value1, attr2: value2, ...}
  313. # raises UnknownError
  314. # raises UnknownIdentifier
  315. if mode != 3:
  316. raise InvalidMode()
  317. _input("read")
  318. _output()
  319. _input(ID)
  320. _output()
  321. if _last_output() == "Unknown element; aborting":
  322. _consume_to_end()
  323. raise UnknownIdentifier()
  324. else:
  325. rval = {}
  326. while (_output() != "Attributes:"):
  327. pass
  328. while (_output() != "Please give your command."):
  329. r = _last_output()
  330. key, value = r.split(":")
  331. _, value = value.split("=")
  332. key = key.strip()
  333. value = value.strip()
  334. value = None if value == "None" else json.loads(value)
  335. rval[key] = value
  336. return rval
  337. def instantiate(typename, edge=None, ID=""):
  338. """Create a new instance of the specified typename, between the selected elements (if not None), and with the provided ID (if any)"""
  339. # return instantiated_ID
  340. # raises UnknownError
  341. # raises UnknownType
  342. # raises UnknownIdentifier
  343. if mode != 3:
  344. raise InvalidMode()
  345. _input("instantiate")
  346. _input(typename)
  347. _input(ID)
  348. if (edge is not None):
  349. _input(edge[0])
  350. _input(edge[1])
  351. def delete(ID):
  352. """Delete the element with the given ID"""
  353. # return None
  354. # raises UnknownError
  355. # raises UnknownIdentifier
  356. if mode != 3:
  357. raise InvalidMode()
  358. _input("delete")
  359. _input(ID)
  360. def attr_assign(ID, attr, value):
  361. """Assign a value to an attribute"""
  362. # return None
  363. # raises UnknownError
  364. # raises UnknownIdentifier
  365. # raises NoSuchAttribute
  366. # raises UnsupportedValue
  367. if mode != 3:
  368. raise InvalidMode()
  369. _input("attr_modify")
  370. _input(ID)
  371. _input(attr)
  372. _input(value)
  373. def attr_assign_code(ID, attr, code):
  374. """Assign a piece of Action Language code to the attribute"""
  375. # return None
  376. # raises UnknownError
  377. # raises UnknownIdentifier
  378. # raises NoSuchAttribute
  379. # raises UnsupportedValue
  380. if mode != 3:
  381. raise InvalidMode()
  382. _input("attr_modify")
  383. _input(ID)
  384. _input(attr)
  385. _compile_AL(code)
  386. def upload(new_model):
  387. """Overwrite the current model with the provided model"""
  388. # return None
  389. # raises UnknownError
  390. # raises CompilationError
  391. if mode != 3:
  392. raise InvalidMode()
  393. _input("upload")
  394. _compile_model(new_model)
  395. def read_outgoing(ID, typename):
  396. """Returns a list of all outgoing associations of a specific type ("" = all)"""
  397. # return [name1, name2, ...]
  398. # raises UnknownError
  399. # raises UnknownIdentifier
  400. # raises UnknownType
  401. if mode != 3:
  402. raise InvalidMode()
  403. _input("read_outgoing")
  404. _input(ID)
  405. _input(typename)
  406. lst = []
  407. while (_output() != "Please give your command."):
  408. lst.append(_last_output())
  409. return lst
  410. def read_incoming(ID, typename):
  411. """Returns a list of all incoming associations of a specific type ("" = all)"""
  412. # return [name1, name2, ...]
  413. # raises UnknownError
  414. # raises UnknownIdentifier
  415. # raises UnknownType
  416. if mode != 3:
  417. raise InvalidMode()
  418. _input("read_incoming")
  419. _input(ID)
  420. _input(typename)
  421. lst = []
  422. while (_output() != "Please give your command."):
  423. lst.append(_last_output())
  424. return lst
  425. def model_exit():
  426. """Leave model modify mode."""
  427. # return None
  428. # raises UnknownError
  429. global mode
  430. if mode != 3:
  431. raise InvalidMode()
  432. _input("exit")
  433. mode = 2
  434. def transformation_add_MT_language():
  435. """Create a new Model Transformation language out of a set of metamodels."""
  436. raise NotImplementedError()
  437. def transformation_add_MT():
  438. """Create a new model transformation."""
  439. raise NotImplementedError()
  440. def transformation_add_AL():
  441. """Create a new action language fragment."""
  442. raise NotImplementedError()
  443. def transformation_add_MANUAL():
  444. """Create a new manual model operation."""
  445. raise NotImplementedError()
  446. def transformation_execute():
  447. """Execute an existing model operation."""
  448. raise NotImplementedError()
  449. def transformation_list():
  450. """List existing model operations."""
  451. raise NotImplementedError()
  452. def transformation_list_full():
  453. """List detailed information on model operations."""
  454. raise NotImplementedError()
  455. def transformation_detail():
  456. """List full details of a a model operation."""
  457. raise NotImplementedError()
  458. def transformation_RAMify():
  459. """Ramify an existing metamodel."""
  460. raise NotImplementedError()
  461. def process_execute():
  462. """Execute a process model."""
  463. raise NotImplementedError()
  464. def permission_modify():
  465. """Modify permissions of a model."""
  466. raise NotImplementedError()
  467. def permission_owner():
  468. """Modify the owning user of a model."""
  469. raise NotImplementedError()
  470. def permission_group():
  471. """Modify the owning group of a model."""
  472. raise NotImplementedError()
  473. def group_create():
  474. """Create a new group."""
  475. raise NotImplementedError()
  476. def group_delete():
  477. """Delete a group of which you are an owner."""
  478. raise NotImplementedError()
  479. def group_owner_add():
  480. """Add a new owning user to a group you own."""
  481. raise NotImplementedError()
  482. def group_owner_delete():
  483. """Delete an owning user to a group you own."""
  484. raise NotImplementedError()
  485. def group_join():
  486. """Add a new user to a group you own."""
  487. raise NotImplementedError()
  488. def group_kick():
  489. """Delete a user from a group you own."""
  490. raise NotImplementedError()
  491. def group_list():
  492. """List existing groups."""
  493. raise NotImplementedError()
  494. def admin_promote():
  495. """Promote a user to admin status."""
  496. raise NotImplementedError()
  497. def admin_demote():
  498. """Demote a user from admin status."""
  499. raise NotImplementedError()