Guest User

Untitled

a guest
Apr 11th, 2018
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.39 KB | None | 0 0
  1. # My first Ruby program
  2. # Author:: Zhybul Kiryl (mailto:lucifer4u@gmail.com)
  3. # Copyright:: Copyright (c) 2007 Zhybul Kiryl
  4. # Revision:: 8
  5. # Created:: 26.08.2007 4:07 (GMT+2)
  6.  
  7.  
  8. # Ideal module have set of tools to create validable structures which can be
  9. # easily transformed to other data types. Once the structure definition and
  10. # transformation tool was created - it can be used anytime with any data which
  11. # passed Ideal Structure validator
  12. module Ideal
  13. # Element is a helper for XML generation
  14. class Element
  15. attr_accessor(:content)
  16.  
  17. def initialize name
  18. @name, @attributes, @content = name, {}, ''
  19. end
  20.  
  21. def attributes= attributes
  22. @attributes.merge(attributes)
  23. end
  24.  
  25. def to_s
  26. open_tag + @content + close_tag
  27. end
  28.  
  29. def open_tag
  30. "<" + @name + delim_and_attr + ">"
  31. end
  32.  
  33. def close_tag
  34. "<" + @name + ">"
  35. end
  36.  
  37. def delim_and_attr
  38. attr_str = attributes_string
  39. attributes_delimiter(attr_str) + attr_str
  40. end
  41.  
  42. def attributes_delimiter attr_s
  43. return ' ' if attr_s != ''
  44. ''
  45. end
  46.  
  47. def attributes_string
  48. attr_s = ''
  49. @attributes.each do |key, value|
  50. attr_s << key + "=" + "'" + value + "'" + " "
  51. end
  52. attr_s.strip
  53. end
  54. end
  55.  
  56. # IdealCollection - container to store Ideal objects with the ability of
  57. # generation to the specific format
  58. class IdealCollection
  59. def initialize
  60. @state = []
  61. end
  62.  
  63. def << value
  64. @state << value if not @state.include?(value)
  65. end
  66.  
  67. def each
  68. @state.each do |value| yield(value) end
  69. end
  70.  
  71. def to_s
  72. @state.to_s
  73. end
  74.  
  75. def generate
  76. result = []
  77. @state.each do |value| result << value.generate() end
  78. end
  79.  
  80. def IdealCollection.is_ideal_collection_structure? structure
  81. structure.all? do |value| Ideal.is_ideal_structure? value end
  82. end
  83.  
  84. end
  85.  
  86. # Ideal - container to store information which can be generated to the special
  87. # format
  88. class Ideal
  89. def initialize
  90. @state = Hash.new {|h, k| h[k] = IdealCollection.new }
  91. end
  92.  
  93. def []= name, value
  94. @state[name] << value
  95. end
  96.  
  97. def [] name
  98. @state[name]
  99. end
  100.  
  101. def to_s
  102. @state.to_s
  103. end
  104.  
  105. def Ideal.is_ideal_structure? struct
  106. return true if (struct.is_a?(String) or struct.is_a?(Numeric))
  107. return false if not struct.is_a?(Hash)
  108. struct.each do |attribute, value|
  109. return false if not attribute.is_a?(String)
  110. return false if not value.is_a?(Array)
  111. return false if value != value.uniq
  112. value.each do |key|
  113. return false if not Ideal.is_ideal_structure?(key)
  114. end
  115. end
  116. true
  117. end
  118.  
  119. def generate
  120. res = {}
  121. @state.each do |attribute, value|
  122. res[attribute] = []
  123. value.each do |key|
  124. if key.respond_to?(:generate)
  125. res[attribute] << key.generate
  126. else
  127. res[attribute] << key
  128. end
  129. end
  130. end
  131. res
  132. end
  133.  
  134. end
  135.  
  136. # Definition of Numeric structure
  137. # Should be used to generate structure definition of Numeric element
  138. class NumericIdealStructureDefinition
  139. attr_accessor(:more_then, :less_then, :regexp, :in, :not_in)
  140. def generate
  141. res = {}
  142. res["more_then"] = @more_then if @more_then != nil
  143. res["less_then"] = @less_then if @less_then != nil
  144. res["regexp" ] = @regexp if @regexp != nil
  145. res["in"] = @in if @in != nil
  146. res["not_in"] = @not_in if @not_in !=nil
  147. res = {Numeric => res}
  148. res
  149. end
  150.  
  151. end
  152.  
  153.  
  154. # Definition of String structure
  155. # Should be used to generate structure definition of String element
  156. class StringIdealStructureDefinition
  157. attr_accessor(:min_length, :max_length, :regexp)
  158.  
  159. def generate
  160. res = {}
  161. res['min_length'] = @min_length if @min_length != nil
  162. res['max_length'] = @max_length if @max_length != nil
  163. res['regexp'] = @regexp if @regexp != nil
  164. {String => res}
  165. end
  166.  
  167. end
  168.  
  169.  
  170. # Definition of Hash structure
  171. # Should be used to generate structure definition of Hash element
  172. class HashIdealStructureDefinition
  173. def initialize
  174. @hash_ideal_structure = {}
  175. end
  176.  
  177. def keys
  178. @hash_ideal_structure.keys
  179. end
  180.  
  181. def []= key, value
  182. @hash_ideal_structure[key] = value
  183. end
  184.  
  185. def generate
  186. res = {}
  187. @hash_ideal_structure.each do |key, value|
  188. res[key] = value.generate
  189. end
  190. {Hash => res}
  191. end
  192.  
  193. end
  194.  
  195.  
  196. # Definition of Ideal Collection structure
  197. # Should be used to generate structure definition of Ideal Collection element
  198. class IdealCollectionStructureDefinition
  199. def min_number= min_number
  200. @min_number = min_number
  201. end
  202.  
  203. def max_number= max_number
  204. @max_number = max_number
  205. end
  206.  
  207. def number_array= number_array
  208. @number_array = number_array
  209. end
  210.  
  211. def ideal_structure= ideal_structure
  212. @ideal_structure = ideal_structure
  213. end
  214.  
  215. def generate
  216. raise "No ideal structure found." if @ideal_structure == nil
  217. res = {}
  218. res["min_number"] = @min_number if @min_number != nil
  219. res["max_number"] = @max_number if @max_number != nil
  220. res["number_array"] = @number_array if @number_array != nil
  221. res["ideal_structure"] = @ideal_structure.generate
  222. res
  223. end
  224.  
  225. end
  226.  
  227.  
  228. # Simple helper to create XML information useing Element objects from
  229. # ideal data structure
  230. class IdealStructureXML
  231. def hash_representation structure
  232. res = ''
  233. structure.each do |key, value|
  234. value.each do |val|
  235. a = Element.new(key)
  236. a.content = render(val)
  237. res = res + a.to_s
  238. end
  239. end
  240. res
  241. end
  242.  
  243. def render structure
  244. return hash_representation(structure) if structure.is_a?(Hash)
  245. structure.to_s
  246. end
  247.  
  248. end
  249.  
  250. # Validator of the ideal structure
  251. # Can tell you is your structure is valid idel structure according to its
  252. # definition
  253.  
  254. class IdealStructureValidator
  255. def validate_hash hash, definition
  256. return false if hash.keys != definition.keys
  257. definition.all? do |key, collection|
  258. validate_collection(hash[key], collection)
  259. end
  260. end
  261.  
  262. def validate_string string, definition
  263. min_length = definition['min_length']
  264. str_length = string.length
  265. max_length = definition['max_length']
  266. regexp = definition['regexp']
  267. return false if (min_length != nil and not str_length >= min_length)
  268. return false if (max_length != nil and not str_length <= max_length)
  269. return false if (regexp != nil and string.scan(regexp).length == 0)
  270. true
  271. end
  272.  
  273. def validate_numeric numeric, definition
  274. more_then = definition['more_then']
  275. less_then = definition['less_then']
  276. regexp = definition['regexp']
  277. in_ = definition['in']
  278. not_in = definition['not_in']
  279. return false if (more_then != nil and not numeric >= more_then)
  280. return false if (less_then != nil and not numeric <= less_then)
  281. return false if (regexp != nil and numeric.to_s.scan(regexp).length == 0)
  282. return false if (in_ != nil and not in_.include?(numeric))
  283. return false if (not_in != nil and not_in.include?(numeric))
  284. true
  285. end
  286.  
  287. def validate_collection collection, definition
  288. length = collection.length
  289. min_number = definition['min_number']
  290. max_number = definition['max_number']
  291. number_arr = definition['number_array']
  292. def_ideal_structure = definition['ideal_structure']
  293. return false if length != collection.uniq.length
  294. return false if (min_number != nil and not length >= min_number)
  295. return false if (max_number != nil and not length <= max_number)
  296. return false if (number_arr != nil and not number_arr.include?(length))
  297. return false if def_ideal_structure == nil
  298. collection.all? do |value| validate(value, def_ideal_structure) end
  299. end
  300.  
  301. def validate input, ideal_structure
  302. ideal_structure.each do |key, value|
  303. return false if not [Hash, String, Numeric].include?(key)
  304. return false if (key == Hash and not validate_hash(input, value))
  305. return false if (key == String and not validate_string(input, value))
  306. return false if (key == Numeric and not validate_numeric(input, value))
  307. end
  308. true
  309. end
  310.  
  311. end
  312.  
  313.  
  314. class IdealTransformation
  315.  
  316. def delimiter info
  317. "<div class='delimiter'>" << info << ":</div>"
  318. end
  319.  
  320. def header
  321. result = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">'
  322. result << "<head>"
  323. result << "<title>"
  324. result << "Test of the Ideal structures"
  325. result << "</title>"
  326. result << "<style type='text/css'>"
  327. result << ".no_users{clear:both; border:1px solid #de7eff;background-color:#eeeeee;color:gray;padding:30px;width:610px;}"
  328. result << ".user_rating{padding:10px;margin:1px;float:left;width:100px;border:1px solid #de7eff;background-color:#eeeeee;color:gray;}"
  329. result << ".user_name{padding:10px;margin:1px;float:left;width:100px;border:1px solid #de7eff;background-color:#eeeeee;color:gray;}"
  330. result << ".user_emails{padding:10px;margin:1px;float:left;width:400px;margin-bottom:10px;border:1px solid #de7eff;background-color:#eeeeee;color:gray;}"
  331. result << ".user{float;left;width:700px;}"
  332. result << ".delimiter{clear:both;}"
  333. result << "</style>"
  334. result << "</head>"
  335. result
  336. end
  337. def transform users_data
  338. result = ''
  339. if users_data['users'].length == 0
  340. result << '<div class="no_users">There is no users in the system</div>'
  341. else
  342. result << '<div class="users">'
  343. users_data['users'].each do |user|
  344. result << '<div class="user">'
  345. result << '<div class="user_name">'
  346. result << user['username'].to_s
  347. result << '</div>'
  348. result << '<div class="user_rating">'
  349. result << user['rating'].to_s
  350. result << '</div>'
  351. result << '<div class="user_emails">'
  352. user['email'].each do |email|
  353. result << '<div class="user_email">'
  354. result << email
  355. result << '</div>'
  356. end
  357. result << '</div>'
  358. result << '</div>'
  359. end
  360. result << '</div>'
  361. end
  362. result
  363. end
  364.  
  365. end
  366. end
  367.  
  368. class Example
  369. def Example.test
  370. # Step 0. Including Ideal module
  371. include Ideal
  372.  
  373. # Step 1. Creation of the ideal descriptor
  374. email_descriptor = StringIdealStructureDefinition.new
  375. email_descriptor.regexp = /[^@]+@[0-9_a-z]+\.[a-z]+/
  376.  
  377. email_collection_descriptor = IdealCollectionStructureDefinition.new
  378. email_collection_descriptor.min_number = 1
  379. email_collection_descriptor.max_number = 4
  380. email_collection_descriptor.ideal_structure = email_descriptor
  381.  
  382. user_rating_descriptor = NumericIdealStructureDefinition.new
  383. user_rating_descriptor.more_then = 0
  384.  
  385. user_rating_collection_descriptor = IdealCollectionStructureDefinition.new
  386. user_rating_collection_descriptor.min_number = 1
  387. user_rating_collection_descriptor.max_number = 1
  388. user_rating_collection_descriptor.ideal_structure = user_rating_descriptor
  389.  
  390. username_descriptor = StringIdealStructureDefinition.new
  391. username_descriptor.regexp = /[0-9A-Za-z_]+/
  392.  
  393. username_collection_descriptor = IdealCollectionStructureDefinition.new
  394. username_collection_descriptor.min_number = 1
  395. username_collection_descriptor.max_number = 1
  396. username_collection_descriptor.ideal_structure = username_descriptor
  397.  
  398. user_descriptor = HashIdealStructureDefinition.new
  399. user_descriptor['username'] = username_collection_descriptor
  400. user_descriptor['rating'] = user_rating_collection_descriptor
  401. user_descriptor['email'] = email_collection_descriptor
  402.  
  403. user_collection_descriptor = IdealCollectionStructureDefinition.new
  404. user_collection_descriptor.min_number = 0
  405. user_collection_descriptor.max_number = 20
  406. user_collection_descriptor.ideal_structure = user_descriptor
  407.  
  408. users_descriptor = HashIdealStructureDefinition.new
  409. users_descriptor['users'] = user_collection_descriptor
  410.  
  411. users_structure_description = users_descriptor.generate
  412.  
  413. # Step 2. Getting data
  414. users_data =
  415. {
  416. "users" =>
  417. [
  418. {
  419. "username" =>
  420. [
  421. "lucifer4u"
  422. ],
  423. "rating" =>
  424. [
  425. 213
  426. ],
  427. "email" =>
  428. [
  429. "lucifer4u@gmail.com",
  430. "lucifer4u@kings.com",
  431. "lucifer4u@swift.com"
  432. ]
  433. },
  434. {
  435. "username" =>
  436. [
  437. "niko"
  438. ],
  439. "rating" =>
  440. [
  441. 324
  442. ],
  443. "email" =>
  444. [
  445. "nikodimous@gmail.com"
  446. ]
  447. },
  448. ]
  449. }
  450.  
  451. users_data_2 =
  452. {
  453. "users" =>
  454. [
  455. ]
  456. }
  457.  
  458. users_data_3 =
  459. {
  460. "users" =>
  461. [
  462. {
  463. "username" =>
  464. [
  465. "niko1"
  466. ],
  467. "rating" =>
  468. [
  469. 3241
  470. ],
  471. "email" =>
  472. [
  473. "nikodimous1@gmail.com"
  474. ]
  475. },
  476. {
  477. "username" =>
  478. [
  479. "niko2"
  480. ],
  481. "rating" =>
  482. [
  483. 3242
  484. ],
  485. "email" =>
  486. [
  487. "nikodimous2@gmail.com"
  488. ]
  489. },
  490. {
  491. "username" =>
  492. [
  493. "niko3"
  494. ],
  495. "rating" =>
  496. [
  497. 3243
  498. ],
  499. "email" =>
  500. [
  501. "nikodimous3@gmail.com"
  502. ]
  503. },
  504. ]
  505. }
  506.  
  507. # Alternative way using Ideal and Ideal Collection
  508. a = Ideal.new
  509. a['username'] = "nightwish"
  510. a['rating'] = 3299
  511. a['email'] = "some_email@gmail.com"
  512. a['email'] << "some_mail@gmail.com"
  513. a['email'] << "extra_mail@gmail.com"
  514.  
  515. b = Ideal.new
  516. b['username'] = "rocky"
  517. b['rating'] = 3929
  518. b['email'] = "rocky@rick.com"
  519. b['email'] = "masters@rick.com"
  520.  
  521. c = Ideal.new
  522. c['users'] = a
  523. c['users'] << b
  524.  
  525. users_data_4 = c.generate
  526.  
  527. # Step 3. Validating information
  528. ideal_structure_validator = IdealStructureValidator.new
  529. is_valid = ideal_structure_validator.validate(users_data,
  530. users_structure_description)
  531.  
  532. is_valid_2 = ideal_structure_validator.validate(users_data_2,
  533. users_structure_description)
  534.  
  535. is_valid_3 = ideal_structure_validator.validate(users_data_3,
  536. users_structure_description)
  537.  
  538. is_valid_4 = ideal_structure_validator.validate(users_data_4,
  539. users_structure_description)
  540.  
  541. # Step 4. Transformation of ideal to some other format
  542. ideal_transformation = IdealTransformation.new
  543.  
  544. puts ideal_transformation.header
  545.  
  546. puts ideal_transformation.delimiter("First data structure representation")
  547. if is_valid
  548. puts ideal_transformation.transform(users_data)
  549. end
  550.  
  551. puts ideal_transformation.delimiter("Second data structure representation")
  552. if is_valid_2
  553. puts ideal_transformation.transform(users_data_2)
  554. end
  555.  
  556. puts ideal_transformation.delimiter("Third data structure representation")
  557. if is_valid_3
  558. puts ideal_transformation.transform(users_data_3)
  559. end
  560.  
  561. puts ideal_transformation.delimiter("Forth data structure representation")
  562. if is_valid_4
  563. puts ideal_transformation.transform(users_data_4)
  564. end
  565. end
  566. end
  567.  
  568. Example.test
Add Comment
Please, Sign In to add comment