modelverse.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632
  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 UnknownException(ModelverseException):
  69. pass
  70. class UnknownIdentifier(ModelverseException):
  71. pass
  72. class UnknownType(ModelverseException):
  73. pass
  74. class NotAnAssociation(ModelverseException):
  75. pass
  76. class UnsupportedValue(ModelverseException):
  77. pass
  78. class CompilationError(ModelverseException):
  79. pass
  80. class NoSuchAttribute(ModelverseException):
  81. pass
  82. class UnknownModel(ModelverseException):
  83. pass
  84. class ConnectionError(ModelverseException):
  85. pass
  86. class ModelExists(ModelverseException):
  87. pass
  88. class PermissionDenied(ModelverseException):
  89. pass
  90. class InvalidMode(ModelverseException):
  91. pass
  92. # Main MvC operations
  93. def init(address_param="http://localhost:8001"):
  94. """Starts up the connection to the Modelverse."""
  95. # return None
  96. # raises ConnectionError
  97. # raises UnknownError
  98. # raises InvalidMode
  99. global mode
  100. if mode != 0:
  101. raise InvalidMode()
  102. global address
  103. address = address_param
  104. try:
  105. _input_raw('"%s"' % taskname, "task_manager")
  106. mode = 1
  107. except URLError as e:
  108. raise ConnectionError(e.reason)
  109. def login(username, password):
  110. """Log in an existing user."""
  111. # return None
  112. # raises UnknownError
  113. # raises PermissionDenied
  114. global mode
  115. if mode != 1:
  116. raise InvalidMode()
  117. _input(username)
  118. _input(password)
  119. _consume_to_end()
  120. mode = 2
  121. def register(username, password):
  122. """Register a new user."""
  123. # return None
  124. # raises UnknownError
  125. # raises UserExists
  126. global mode
  127. if mode != 1:
  128. raise InvalidMode()
  129. _input(username)
  130. _input(password)
  131. _input(password)
  132. _consume_to_end()
  133. mode = 2
  134. def model_add(model_name, metamodel_name, model_code=None):
  135. """Instantiate a new model."""
  136. # return None
  137. # raises UnknownModel
  138. # raises ModelExists
  139. # raises UnknownError
  140. # raises PermissionDenied
  141. # raises CompilationError
  142. if mode != 2:
  143. raise InvalidMode()
  144. _input("model_add")
  145. _output()
  146. _output()
  147. _input(metamodel_name)
  148. if _output() == "Model name?":
  149. _input(model_name)
  150. if _output() == "Waiting for model constructors...":
  151. try:
  152. if model_code == None:
  153. _input("exit")
  154. else:
  155. _compile_model(model_code)
  156. except Exception:
  157. raise CompilationError()
  158. _consume_to_end()
  159. else:
  160. _consume_to_end()
  161. raise ModelExists()
  162. elif _last_output() == "Could not find type model!":
  163. _consume_to_end()
  164. raise UnknownModel()
  165. elif _last_output() == "Permission denied":
  166. _consume_to_end()
  167. raise PermissionDenied()
  168. def model_modify(model_name):
  169. """Modify an existing model."""
  170. # return is_write
  171. # raises UnknownModel
  172. # raises PermissionDenied
  173. # raises UnknownError
  174. global mode
  175. if mode != 2:
  176. raise InvalidMode()
  177. _input("model_modify")
  178. _output()
  179. _input(model_name)
  180. if _output() == "Permission denied":
  181. _consume_to_end()
  182. raise PermissionDenied()
  183. elif _last_output() == "Could not find model!":
  184. _consume_to_end()
  185. raise UnknownModel()
  186. elif _last_output() == "Model loaded, ready for commands!":
  187. mode = 3
  188. if ("r/w" in _output()):
  189. write = True
  190. else:
  191. write = False
  192. _consume_to_end()
  193. return write
  194. else:
  195. _consume_to_end()
  196. raise UnknownException()
  197. def model_list():
  198. """List all models."""
  199. # return [(model1, metamodel1), (model2, metamodel2), ...]
  200. # raises UnknownError
  201. if mode != 2:
  202. raise InvalidMode()
  203. _input("model_list")
  204. lst = []
  205. while (_output() != "Ready for command..."):
  206. v = _last_output()
  207. m, mm = v.split(":")
  208. m = m.strip()
  209. mm = mm.strip()
  210. lst.append((m, mm))
  211. return lst
  212. def model_list_full():
  213. """List full information on all models."""
  214. # return [(model1, metamodel1, owner1, group1, permissions1), (model2, metamodel2, owner2, group2, permissions2), ...]
  215. # raises UnknownError
  216. if mode != 2:
  217. raise InvalidMode()
  218. _input("model_list_full")
  219. lst = []
  220. while (_output() != "Ready for command..."):
  221. v = _last_output()
  222. m, mm = v.split(":")
  223. m = m.strip()
  224. mm = mm.strip()
  225. perm, own, grp, m = m.split(" ")
  226. lst.append((m, mm, own, grp, perm))
  227. return lst
  228. def model_overwrite(model_name, new_model):
  229. """Upload a new model and overwrite an existing model."""
  230. # return None
  231. # raises UnknownModel
  232. # raises PermissionDenied
  233. # raises CompilationError
  234. # raises UnknownError
  235. if mode != 2:
  236. raise InvalidMode()
  237. _input("model_overwrite")
  238. _input(model_name)
  239. _compile_model(new_model)
  240. def user_logout():
  241. """Log out the current user. A new login will be required afterwards."""
  242. # return None
  243. # raises UnknownException
  244. global mode
  245. if mode != 2:
  246. raise InvalidMode()
  247. _input("exit")
  248. mode = 1
  249. def user_delete():
  250. """Removes the current user. A new login will be required afterwards."""
  251. # return None
  252. # raises UnknownException
  253. global mode
  254. if mode != 2:
  255. raise InvalidMode()
  256. _input("self-destruct")
  257. mode = 1
  258. # Actual operations on the model
  259. def element_list():
  260. """Return a list of all IDs and the type of the element"""
  261. # return [(name1, type1), (name2, type2), ...]
  262. # raises UnknownError
  263. if mode != 3:
  264. raise InvalidMode()
  265. _input("list")
  266. lst = []
  267. _output()
  268. while (_output() != "Please give your command."):
  269. v = _last_output()
  270. m, mm = v.split(":")
  271. m = m.strip()
  272. mm = mm.strip()
  273. lst.append((m, mm))
  274. return lst
  275. def types():
  276. """Return a list of all types usable in the model"""
  277. # return [type1, type2, ...]
  278. # raises UnknownError
  279. if mode != 3:
  280. raise InvalidMode()
  281. _input("types")
  282. _output()
  283. lst = []
  284. while (_output() != "Please give your command."):
  285. v = _last_output()
  286. m, mm = v.split(":")
  287. m = m.strip()
  288. lst.append(m)
  289. return lst
  290. def read(ID):
  291. """Return a tuple of information on the element: its type and source/target (None if not an edge)"""
  292. # return (type, (source, target))
  293. # raises UnknownError
  294. # raises UnknownIdentifier
  295. if mode != 3:
  296. raise InvalidMode()
  297. _input("read")
  298. _output()
  299. _input(ID)
  300. _output()
  301. if _last_output() == "Unknown element; aborting":
  302. _consume_to_end()
  303. raise UnknownIdentifier()
  304. else:
  305. t = _output().split(":")[1].strip()
  306. if (not _output().startswith("Source:")):
  307. rval = (t, None)
  308. else:
  309. src = _last_output().split(":")[1].strip()
  310. trg = _output().split(":")[1].strip()
  311. rval = (t, (src, trg))
  312. while (_output() != "Please give your command."):
  313. pass
  314. return rval
  315. def read_attrs(ID):
  316. """Return a dictionary of attribute value pairs"""
  317. # return {attr1: value1, attr2: value2, ...}
  318. # raises UnknownError
  319. # raises UnknownIdentifier
  320. if mode != 3:
  321. raise InvalidMode()
  322. _input("read")
  323. _output()
  324. _input(ID)
  325. _output()
  326. if _last_output() == "Unknown element; aborting":
  327. _consume_to_end()
  328. raise UnknownIdentifier()
  329. else:
  330. rval = {}
  331. while (_output() != "Attributes:"):
  332. pass
  333. while (_output() != "Please give your command."):
  334. r = _last_output()
  335. key, value = r.split(":")
  336. _, value = value.split("=")
  337. key = json.loads(key.strip())
  338. value = value.strip()
  339. value = None if value == "None" else json.loads(value)
  340. rval[key] = value
  341. return rval
  342. def instantiate(typename, edge=None, ID=""):
  343. """Create a new instance of the specified typename, between the selected elements (if not None), and with the provided ID (if any)"""
  344. # return instantiated_ID
  345. # raises UnknownError
  346. # raises UnknownType
  347. # raises UnknownIdentifier
  348. # raises NotAnEdge
  349. if mode != 3:
  350. raise InvalidMode()
  351. _input("instantiate")
  352. if (_output() == "Permission denied"):
  353. _consume_to_end()
  354. raise PermissionDenied()
  355. else:
  356. _input(typename)
  357. if (_output() == "Name of new element?"):
  358. _input(ID)
  359. if (_output() == "Element already exists; aborting"):
  360. _consume_to_end()
  361. raise ElementExists()
  362. if (edge is not None):
  363. if (_last_output() == "Source name?"):
  364. _input(edge[0])
  365. if (_output() != "Destination name?"):
  366. _consume_to_end()
  367. raise UnknownIdentifier()
  368. _input(edge[1])
  369. ID = _output()
  370. if (ID == "Unknown destination; aborting"):
  371. _consume_to_end()
  372. raise UnknownIdentifier()
  373. else:
  374. _consume_to_end()
  375. return ID
  376. else:
  377. _consume_to_end()
  378. raise NotAnEdge()
  379. else:
  380. ID = _last_output()
  381. _consume_to_end()
  382. return ID
  383. elif (_last_output() == "Permission denied"):
  384. _consume_to_end()
  385. raise PermissionDenied()
  386. elif (_last_output() == "Unknown type specified; aborting"):
  387. _consume_to_end()
  388. raise UnknownType()
  389. else:
  390. print(9)
  391. print(_last_output())
  392. def delete(ID):
  393. """Delete the element with the given ID"""
  394. # return None
  395. # raises UnknownError
  396. # raises UnknownIdentifier
  397. if mode != 3:
  398. raise InvalidMode()
  399. _input("delete")
  400. _input(ID)
  401. def attr_assign(ID, attr, value):
  402. """Assign a value to an attribute"""
  403. # return None
  404. # raises UnknownError
  405. # raises UnknownIdentifier
  406. # raises NoSuchAttribute
  407. # raises UnsupportedValue
  408. if mode != 3:
  409. raise InvalidMode()
  410. _input("attr_modify")
  411. _input(ID)
  412. _input(attr)
  413. _input(value)
  414. _consume_to_end()
  415. def attr_assign_code(ID, attr, code):
  416. """Assign a piece of Action Language code to the attribute"""
  417. # return None
  418. # raises UnknownError
  419. # raises UnknownIdentifier
  420. # raises NoSuchAttribute
  421. # raises UnsupportedValue
  422. if mode != 3:
  423. raise InvalidMode()
  424. _input("attr_modify")
  425. _input(ID)
  426. _input(attr)
  427. _compile_AL(code)
  428. def upload(new_model):
  429. """Overwrite the current model with the provided model"""
  430. # return None
  431. # raises UnknownError
  432. # raises CompilationError
  433. if mode != 3:
  434. raise InvalidMode()
  435. _input("upload")
  436. _compile_model(new_model)
  437. def read_outgoing(ID, typename):
  438. """Returns a list of all outgoing associations of a specific type ("" = all)"""
  439. # return [name1, name2, ...]
  440. # raises UnknownError
  441. # raises UnknownIdentifier
  442. # raises UnknownType
  443. if mode != 3:
  444. raise InvalidMode()
  445. _input("read_outgoing")
  446. _input(ID)
  447. _input(typename)
  448. lst = []
  449. while (_output() != "Please give your command."):
  450. lst.append(_last_output())
  451. return lst
  452. def read_incoming(ID, typename):
  453. """Returns a list of all incoming associations of a specific type ("" = all)"""
  454. # return [name1, name2, ...]
  455. # raises UnknownError
  456. # raises UnknownIdentifier
  457. # raises UnknownType
  458. if mode != 3:
  459. raise InvalidMode()
  460. _input("read_incoming")
  461. _input(ID)
  462. _input(typename)
  463. lst = []
  464. while (_output() != "Please give your command."):
  465. lst.append(_last_output())
  466. return lst
  467. def read_association_source(ID):
  468. """Returns the source of an association."""
  469. pass
  470. # returns name
  471. # raises UnknownError
  472. # raises UnknownIdentifier
  473. # raises NotAnAssociation
  474. def read_association_destination(ID):
  475. """Returns the destination of an association."""
  476. pass
  477. # returns name
  478. # raises UnknownError
  479. # raises UnknownIdentifier
  480. # raises NotAnAssociation
  481. def model_exit():
  482. """Leave model modify mode."""
  483. # return None
  484. # raises UnknownError
  485. global mode
  486. if mode != 3:
  487. raise InvalidMode()
  488. _input("exit")
  489. _consume_to_end()
  490. mode = 2
  491. def transformation_add_MT_language():
  492. """Create a new Model Transformation language out of a set of metamodels."""
  493. raise NotImplementedError()
  494. def transformation_add_MT():
  495. """Create a new model transformation."""
  496. raise NotImplementedError()
  497. def transformation_add_AL():
  498. """Create a new action language fragment."""
  499. raise NotImplementedError()
  500. def transformation_add_MANUAL():
  501. """Create a new manual model operation."""
  502. raise NotImplementedError()
  503. def transformation_execute():
  504. """Execute an existing model operation."""
  505. raise NotImplementedError()
  506. def transformation_list():
  507. """List existing model operations."""
  508. raise NotImplementedError()
  509. def transformation_list_full():
  510. """List detailed information on model operations."""
  511. raise NotImplementedError()
  512. def transformation_detail():
  513. """List full details of a a model operation."""
  514. raise NotImplementedError()
  515. def transformation_RAMify():
  516. """Ramify an existing metamodel."""
  517. raise NotImplementedError()
  518. def process_execute():
  519. """Execute a process model."""
  520. raise NotImplementedError()
  521. def permission_modify():
  522. """Modify permissions of a model."""
  523. raise NotImplementedError()
  524. def permission_owner():
  525. """Modify the owning user of a model."""
  526. raise NotImplementedError()
  527. def permission_group():
  528. """Modify the owning group of a model."""
  529. raise NotImplementedError()
  530. def group_create():
  531. """Create a new group."""
  532. raise NotImplementedError()
  533. def group_delete():
  534. """Delete a group of which you are an owner."""
  535. raise NotImplementedError()
  536. def group_owner_add():
  537. """Add a new owning user to a group you own."""
  538. raise NotImplementedError()
  539. def group_owner_delete():
  540. """Delete an owning user to a group you own."""
  541. raise NotImplementedError()
  542. def group_join():
  543. """Add a new user to a group you own."""
  544. raise NotImplementedError()
  545. def group_kick():
  546. """Delete a user from a group you own."""
  547. raise NotImplementedError()
  548. def group_list():
  549. """List existing groups."""
  550. raise NotImplementedError()
  551. def admin_promote():
  552. """Promote a user to admin status."""
  553. raise NotImplementedError()
  554. def admin_demote():
  555. """Demote a user from admin status."""
  556. raise NotImplementedError()