ontomde-core 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,316 +1,410 @@
1
- #:include: ../shared/license.rdoc
2
-
3
- #require "ontomde-core/exceptions.rb"
4
- require "singleton"
5
-
6
- # Helper methods to handle rdf ressources as object.
7
- module IteratorOrSingleElement
8
- def to_s
9
- r=""
10
- sep=""
11
- self.each{ |elt|
12
- r=r+sep+(elt.to_s)
13
- sep=" "
14
- }
15
- return r
16
- end
17
- def isFalse?
18
- return !isTrue?
19
- end
20
- def +(array)
21
- return self if array.kind_of?(ArrayOrSingleElementEmpty)
22
- return super(array)
23
- end
24
-
25
- STRING_TO_BOOLEAN_HASH={ "false" => false, "true" => true}
26
- def other_implem_isTrue?
27
- return false if length==0
28
- raise Warning.new,"bad data for isTrue?(length=#{length}>1)" if length>1
29
- ret=STRING_TO_BOOLEAN_HASH[self[0]]
30
- return ret unless ret.nil?
31
- raise Warning.new,"bad data for isTrue?(#{self[0]})" if length>1
32
- end
33
- def isTrue?
34
- #return false if length==0
35
- return false if empty?
36
- raise Warning.new,"bad data for isTrue?(length=#{length}>1)" if length>1
37
- return false if self[0]=="false"
38
- return true if self[0]=="true"
39
- raise Warning.new,"bad data for isTrue?(#{self[0]})" if length>1
40
-
41
- end
42
- end
43
- class ArrayOrSingleElement < Array
44
- include IteratorOrSingleElement
45
- end
46
- class SetOrSingleElement < Set
47
- include IteratorOrSingleElement end
48
-
49
- # Singleton of an empty ArrayOrSingleElement
50
- # Note:
51
- # This object is used for performance enhancement.
52
- class ArrayOrSingleElementEmpty #< ArrayOrSingleElement
53
- include Singleton
54
-
55
- # Size of an empty Array (always 0)
56
- def size
57
- 0
58
- end
59
-
60
- # Size of an empty Array (always 0)
61
- def length
62
- 0
63
- end
64
-
65
- # Iterator (does nothing)
66
- def each
67
- end
68
-
69
- # returns self as
70
- def select
71
- # quelque-soit le critere
72
- # de selection le retour est tout aussi vide
73
- return self;
74
- end
75
-
76
- # returns array
77
- def +(array)
78
- return array
79
- end
80
-
81
- # returns !isTrue?
82
- def isFalse?
83
- return !isTrue?
84
- end
85
-
86
- # returns false
87
- def isTrue?
88
- return false
89
- end
90
-
91
- # returns ""
92
- def to_s
93
- return ""
94
- end
95
-
96
- #return true
97
- def empty?
98
- return true
99
- end
100
-
101
- #returns false
102
- def include?(elt)
103
- return false
104
- end
105
-
106
- def delete(elt)
107
- return nil
108
- end
109
-
110
- def sort(&block)
111
- return self
112
- end
113
- end
114
-
115
-
116
-
117
- module Kernel
118
- #Creates accessors for rdf property passed as argument.
119
- #
120
- #Example:
121
- # for rdf_safe_attr_reader_many uml_abcde_efgh
122
- # the following methods are generated
123
- #
124
- # def uml_abcd_efgh ()
125
- # returns an Array of reference elements.
126
- # (This array is READ-ONLY)
127
- #
128
- # def uml_efgh ()
129
- # same as uml_abcd_efgh
130
- # in case of name clashing use long version.
131
- #
132
- # def uml_efgh_one()
133
- # Returns nil if array is empty
134
- # Triggers an error if array contains more than one element.
135
- # returns the first element of array
136
- #
137
- # def uml_efgh=(x)
138
- # reset array and add x
139
- #
140
- # def uml_efgh_add(x)
141
- # add x to the existing array
142
- #
143
- # def uml_efgh?
144
- # returns uml_efgh.isTrue?()
145
- #
146
- def rdf_safe_attr_reader_many(*syms)
147
- #attr_reader(*args)
148
- # TODO: ne pas crer un objet vide syst�matiquement.
149
- syms.each do |sym|
150
- #sym_array=sym.to_s.split("_",3)
151
- #sym_short=""
152
- #if sym_array[0]=="uml" && sym_array[2]!=""
153
- # sym_short="#{sym_array[0]}_#{sym_array[2]}"
154
- #else
155
- sym_short=sym
156
- #end
157
- #version normale
158
- #TODO: supprimer la version normale
159
- # ou raccourcir les nom en amont
160
- #class_eval %{def #{sym}
161
- # log.warn "method #{sym} is deprecated. Use #{sym_short} instead"
162
- # @#{sym}.nil? ? ::ArrayOrSingleElementEmpty.instance : @#{sym}
163
- #end}
164
- #version courte
165
-
166
- #log.debug "sym_short: >#{sym_array[0]}< >#{sym_array[1]}< >#{sym_array[2]}<"
167
- #log.debug sym_short
168
- class_eval %{def #{sym_short}
169
- @#{sym}.nil? ? ::ArrayOrSingleElementEmpty.instance : @#{sym}
170
- end}
171
-
172
- Crdf_Resource.class_eval %{def #{sym_short}_inv
173
- ret=nil
174
- ext_isReferencedBy.each { |g|
175
- next unless g.respond_to?(:#{sym_short})
176
- next unless g.#{sym_short}.include?(self)
177
- ret=::ArrayOrSingleElement.new if ret.nil?
178
- next if ret.include?(g)
179
- ret << g
180
- }
181
- ret.nil? ? ::ArrayOrSingleElementEmpty.instance : ret
182
- end}
183
-
184
- Crdf_Resource.class_eval %{def #{sym_short}_inv_one(warn=true)
185
- i=#{sym_short}_inv
186
- if i.nil? || i.size==0
187
- log_error_nil_one("#{sym_short}_inv") if warn
188
- return nil
189
- end
190
- return i[0] if i.length==1
191
- log.error "#{sym_short}_inv_one used with multi-value (class=\#{self.class.name})(uri=\#{rdf_uri})(length=\#{@#{sym}.length})(value=(\#{@#{sym}.to_s}) Returning first one found as workaround : (\#{@#{sym}[0]})"
192
- return i[0]
193
- end}
194
-
195
- class_eval %{def #{sym_short}?
196
- return #{sym_short}.isTrue?
197
- end}
198
-
199
- class_eval %{def #{sym_short}_one(warn=true)
200
- if @#{sym}.nil? || @#{sym}.size==0
201
- log_error_nil_one("#{sym_short}") if warn
202
- return nil
203
- end
204
- return @#{sym}[0] if @#{sym}.length==1
205
- #log.error Warning.new,"#{sym_short}_one used with multi-value (class=\#{self.class.name})(uri=\#{rdf_uri})(length=\#{@#{sym}.length})(value=(\#{@#{sym}.to_s})"
206
- log.error "#{sym_short}_one used with multi-value (class=\#{self.class.name})(uri=\#{rdf_uri})(length=\#{@#{sym}.length})(value=(\#{@#{sym}.to_s}) Returning first one found as workaround : (\#{@#{sym}[0]})"
207
- return @#{sym}[0]
208
- end}
209
-
210
- class_eval %{def #{sym_short}_one0()
211
- #{sym_short}_one(false)
212
- end}
213
-
214
-
215
- inv=(sym_short.to_s=="ext_isReferencedBy") ? "" : "item.ext_isReferencedBy_add(self) if item.respond_to?(:ext_isReferencedBy_add) "
216
-
217
- #puts "sym_short=#{sym_short} #{inv}"
218
-
219
- #puts "adding method def #{sym_short}=(v) for #{self.name}"
220
- class_eval %{def #{sym_short}=(v)
221
- if v.nil?
222
- @#{sym}=nil
223
- elsif v.kind_of?(ArrayOrSingleElement) || v.kind_of?(Array) || v.kind_of?(ArrayOrSingleElementEmpty)
224
- @#{sym}= ArrayOrSingleElement.new
225
- v.each { |item|
226
- @#{sym}.push(item)
227
- #{inv}
228
- }
229
- else
230
- @#{sym}= ArrayOrSingleElement.new
231
- @#{sym}.push(v)
232
- item=v
233
- #{inv}
234
- end
235
- end}
236
-
237
- class_eval %{def #{sym_short}_add(item)
238
- if !item.nil?
239
- #log.debug @#{sym}.size+1000
240
- if @#{sym}.nil?
241
- #log.debug "reset @#{sym}"
242
- @#{sym}= ArrayOrSingleElement.new
243
- end
244
- @#{sym}.push(item)
245
- #{inv}
246
- end
247
- end}
248
-
249
-
250
- end
251
- end
252
- end
253
-
254
- module Mrdf_Model
255
- def mtk_object_message
256
- return ""
257
- end
258
- def mtk_related_message
259
- return ""
260
- end
261
- end
262
-
263
- module Mrdf_Resource
264
- #return a string describing this object
265
- #(used for error log messages)
266
- def mtk_object_message
267
- return <<END
268
- ** uri =#{rdf_uri}
269
- ** type=#{self.class.name}
270
- ** to_s=#{self.to_s}
271
- END
272
- end
273
- #return a string describing object related to this object
274
- #(used for error log messages)
275
- def mtk_related_message
276
- related=""
277
- ext_isReferencedBy.each { |g|
278
- related=related+"** (#{g.class.name}) #{g}\n"
279
- }
280
- return related
281
- end
282
-
283
-
284
- # generates an error message used when
285
- # "meth" returns unexpectedly no data.
286
- def log_error_nil_one(meth)
287
- return if log_already_displayed?("#{rdf_uri}__#{meth}")
288
- log.error {
289
-
290
- <<-END
291
- #{meth}_one nil for #{self}::#{self.class.name} (uri=#{rdf_uri})
292
- ********* INVALID DATA DETECTED **********
293
- ** This software expects the model element specified bellow
294
- **#{mtk_object_message}
295
- ** to have exactly one "#{meth}".
296
- **
297
- ** This is most likely caused by a missing data in source model.
298
- ** Please check that previous element has a #{meth} defined.
299
- **
300
- ** This model element is related to these other model elements:
301
- #{mtk_related_message}
302
- ********* INVALID DATA DETECTED **********
303
- END
304
- }
305
- raise Warning.new,"#{meth}_one nil null" if context[:failOnEmptyCallto_one,true]
306
- end
307
- end
308
-
309
- #List of error message keys already displayed
310
- MDA_LOG_ALREADY_DISPLAYED=Array.new
311
-
312
- def log_already_displayed?(key)
313
- return true if MDA_LOG_ALREADY_DISPLAYED.include?(key)
314
- MDA_LOG_ALREADY_DISPLAYED<< key
315
- return false
316
- end
1
+
2
+ #require "ontomde-core/exceptions.rb"
3
+ require "singleton"
4
+
5
+ # Helper methods to handle rdf ressources as object.
6
+ module IteratorOrSingleElement
7
+ def to_s
8
+ r=""
9
+ sep=""
10
+ self.each{ |elt|
11
+ r=r+sep+(elt.to_s)
12
+ sep=" "
13
+ }
14
+ return r
15
+ end
16
+ def isFalse?
17
+ return !isTrue?
18
+ end
19
+ def +(array)
20
+ return self if array.kind_of?(ArrayOrSingleElementEmpty)
21
+ return super(array)
22
+ end
23
+
24
+ STRING_TO_BOOLEAN_HASH={ "false" => false, "true" => true}
25
+ def other_implem_isTrue?
26
+ return false if length==0
27
+ raise Warning.new,"bad data for isTrue?(length=#{length}>1)" if length>1
28
+ ret=STRING_TO_BOOLEAN_HASH[self[0]]
29
+ return ret unless ret.nil?
30
+ raise Warning.new,"bad data for isTrue?(#{self[0]})" if length>1
31
+ end
32
+ def isTrue?
33
+ #return false if length==0
34
+ return false if empty?
35
+ raise Warning.new,"bad data for isTrue?(length=#{length}>1)" if length>1
36
+ return false if self[0]=="false"
37
+ return true if self[0]=="true"
38
+ raise Warning.new,"bad data for isTrue?(#{self[0]})" if length>1
39
+
40
+ end
41
+ end
42
+ class ArrayOrSingleElement < Array
43
+ include IteratorOrSingleElement
44
+ end
45
+ class SetOrSingleElement < Set
46
+ include IteratorOrSingleElement end
47
+
48
+ # Singleton of an empty ArrayOrSingleElement
49
+ # Note:
50
+ # This object is used for performance enhancement.
51
+ class ArrayOrSingleElementEmpty #< ArrayOrSingleElement
52
+ include Singleton
53
+
54
+ # Size of an empty Array (always 0)
55
+ def size
56
+ 0
57
+ end
58
+
59
+ # Size of an empty Array (always 0)
60
+ def length
61
+ 0
62
+ end
63
+
64
+ # Iterator (does nothing)
65
+ def each
66
+ end
67
+
68
+ # returns self as
69
+ def select
70
+ # quelque-soit le critere
71
+ # de selection le retour est tout aussi vide
72
+ return self;
73
+ end
74
+
75
+ # returns array
76
+ def +(array)
77
+ return array
78
+ end
79
+
80
+ # returns !isTrue?
81
+ def isFalse?
82
+ return !isTrue?
83
+ end
84
+
85
+ # returns false
86
+ def isTrue?
87
+ return false
88
+ end
89
+
90
+ # returns ""
91
+ def to_s
92
+ return ""
93
+ end
94
+
95
+ #return true
96
+ def empty?
97
+ return true
98
+ end
99
+
100
+ #returns false
101
+ def include?(elt)
102
+ return false
103
+ end
104
+
105
+ def delete(elt)
106
+ return nil
107
+ end
108
+
109
+ def sort(&block)
110
+ return self
111
+ end
112
+ end
113
+
114
+ module Mrdfs_Literal
115
+ end
116
+ class Crdf_Resource
117
+
118
+ # helper method used by rdf property getter
119
+ # return first value contained in val ArrayOrSingleElement
120
+ #
121
+ # When val is empty:
122
+ # log an error if warn==true
123
+ # returns nil
124
+ # When val contains more than one element:
125
+ # log an error
126
+ # returns first element found
127
+ def rdf_getter_one(val,warn,propNameShort)
128
+ if val.nil? || val.size==0
129
+ log_error_nil_one(propNameShort) if warn
130
+ return nil
131
+ end
132
+ return val[0] if val.length==1
133
+ log.error "#{propNameShort}_one used with multi-value (class=#{self.class.name})(uri=#{rdf_uri})(length=#{val.length})(value=(#{val.to_s}) Returning first one found as workaround : (#{val[0]})"
134
+ return val[0]
135
+ end
136
+ # raise an exception if value does not have a type in range array.
137
+ # This method is used by rdf attributes operators.
138
+ #
139
+ # range: array of types
140
+ # value: a value
141
+ # property: name of the property, value comes from (used in error message)
142
+ def check_rdfType(range,value,property)
143
+ return if value.nil?
144
+ return if range.empty?
145
+ range.each { |r|
146
+ return if value.kind_of?(r)
147
+ return if r==::Mrdfs_Literal && (value.kind_of?(String) || value.kind_of?(Fixnum))
148
+ }
149
+ raise Exception.new(
150
+ <<END
151
+
152
+ ********* ILLEGAL ASSIGNEMENT TYPE **********
153
+ ** property #{property}
154
+ ** has a range of (valid value types)
155
+ ** [ #{range} ]
156
+ ** which is not compatible with type #{value.class.name}
157
+ ** Please check your code for incorrect assignement.
158
+ **
159
+ ** This model element is related to these other model elements:
160
+ #{mtk_related_message}
161
+ ********* ILLEGAL ASSIGNEMENT TYPE **********
162
+ END
163
+ )
164
+ end
165
+
166
+ # helper method used by rdf property
167
+ # to retrieve the inverse of a property.
168
+ #
169
+ # This method return is randomly ordered
170
+ #
171
+ # sym_short: name of the inverse property
172
+ # filter: method calling the direct property
173
+ # (used for performance reason to avoid eval)
174
+ def rdf_getter_inv(sym_short,&filter)
175
+ ret=nil
176
+ ext_isReferencedBy.each { |g|
177
+ next unless g.respond_to?(sym_short)
178
+ next unless yield(g).include?(self)
179
+ ret=::ArrayOrSingleElement.new if ret.nil?
180
+ next if ret.include?(g)
181
+ ret << g
182
+ }
183
+ return ret.nil? ? ::ArrayOrSingleElementEmpty.instance : ret
184
+ end
185
+ end
186
+
187
+ module Kernel
188
+
189
+ #Creates accessors for rdf property passed as argument.
190
+ #
191
+ #Example:
192
+ # for rdf_safe_attr_reader_many uml_abcde_efgh
193
+ # the following methods are generated
194
+ #
195
+ # def uml_abcd_efgh ()
196
+ # returns an Array of reference elements.
197
+ # (This array is READ-ONLY)
198
+ #
199
+ # def uml_efgh ()
200
+ # same as uml_abcd_efgh
201
+ # in case of name clashing use long version.
202
+ #
203
+ # def uml_efgh_one()
204
+ # Returns nil if array is empty
205
+ # Triggers an error if array contains more than one element.
206
+ # returns the first element of array
207
+ #
208
+ # def uml_efgh=(x)
209
+ # reset array and add x
210
+ #
211
+ # def uml_efgh_add(x)
212
+ # add x to the existing array
213
+ #
214
+ # def uml_efgh?
215
+ # returns uml_efgh.isTrue?()
216
+ #
217
+ def rdf_safe_attr_reader_many(*syms)
218
+ syms.each { |s|
219
+ rdf_attr_rubyCode(s,[]).each { |code|
220
+ class_eval code
221
+ }
222
+ }
223
+ end
224
+
225
+ #creates rdf attribute and accessors
226
+ def rdf_attr(sym,range)
227
+ rdf_attr_rubyCode(sym,range).each { |code|
228
+ class_eval code
229
+ }
230
+ end
231
+
232
+ # returns ruby code generated for rdf attribute and accessors.
233
+ def rdf_attr_rubyCode(sym,range)
234
+ ret=[]
235
+ # TODO: ne pas crer un objet vide systématiquement.
236
+
237
+ #sym_array=sym.to_s.split("_",3)
238
+ #sym_short=""
239
+ #if sym_array[0]=="uml" && sym_array[2]!=""
240
+ # sym_short="#{sym_array[0]}_#{sym_array[2]}"
241
+ #else
242
+ sym_short=sym
243
+ #end
244
+ #version normale
245
+ #TODO: supprimer la version normale
246
+ # ou raccourcir les nom en amont
247
+ #class_eval %{def #{sym}
248
+ # log.warn "method #{sym} is deprecated. Use #{sym_short} instead"
249
+ # @#{sym}.nil? ? ::ArrayOrSingleElementEmpty.instance : @#{sym}
250
+ #end}
251
+ #version courte
252
+
253
+ #log.debug "sym_short: >#{sym_array[0]}< >#{sym_array[1]}< >#{sym_array[2]}<"
254
+ #log.debug sym_short
255
+ ret << %{def #{sym_short}
256
+ @#{sym}.nil? ? ::ArrayOrSingleElementEmpty.instance : @#{sym}
257
+ end}
258
+
259
+ (range.empty?&&true ? [Crdf_Resource] : range).each { |inv_res|
260
+ next if inv_res==::Mrdfs_Literal
261
+ inv_res.class_eval <<END
262
+ def #{sym_short}_inv
263
+ return rdf_getter_inv(:#{sym_short}) { |g| g.#{sym_short} }
264
+ end
265
+ def #{sym_short}_inv_one()
266
+ return rdf_getter_one(#{sym_short}_inv,true,:#{sym_short}_inv)
267
+ end
268
+ def #{sym_short}_inv_one0()
269
+ return rdf_getter_one(#{sym_short}_inv,false,:#{sym_short}_inv)
270
+ end
271
+ END
272
+ }
273
+
274
+
275
+ range_array="["; sep=""
276
+ range.each { |r|
277
+ range_array+=sep+r.name #.getRubyModuleName
278
+ sep=","
279
+ }
280
+ range_array+="]"
281
+
282
+ if (true)
283
+ ret << %{def #{sym_short}_typeOk?(val)
284
+ check_rdfType(#{range_array},val,:#{sym_short})
285
+ end
286
+ }
287
+ else
288
+ # TODO: more performant but generates warnings
289
+ # investigate reason of multiple execution
290
+ ret << %{RANGE_#{sym_short}=#{range_array}
291
+ def #{sym_short}_typeOk?(val)
292
+ check_rdfType(RANGE_#{sym_short},val,:#{sym_short})
293
+ end
294
+ }
295
+ end
296
+
297
+ ret << %{def #{sym_short}?
298
+ return #{sym_short}.isTrue?
299
+ end}
300
+
301
+ ret << %{def #{sym_short}_one()
302
+ return rdf_getter_one(@#{sym},true,:#{sym_short})
303
+ end}
304
+
305
+ ret << %{def #{sym_short}_one0()
306
+ return rdf_getter_one(@#{sym},false,:#{sym_short})
307
+ end}
308
+
309
+ inv=(sym_short.to_s=="ext_isReferencedBy") ? "" : "item.ext_isReferencedBy_add(self) if item.respond_to?(:ext_isReferencedBy_add) "
310
+
311
+ ret << %{def #{sym_short}=(v)
312
+ if v.nil?
313
+ @#{sym}=nil
314
+ elsif v.kind_of?(ArrayOrSingleElement) || v.kind_of?(Array) || v.kind_of?(ArrayOrSingleElementEmpty)
315
+ @#{sym}= ArrayOrSingleElement.new
316
+ v.each { |item|
317
+ #{sym_short}_typeOk?(item)
318
+ @#{sym}.push(item)
319
+ #{inv}
320
+ }
321
+ else
322
+ @#{sym}= ArrayOrSingleElement.new
323
+ #{sym_short}_typeOk?(v)
324
+ @#{sym}.push(v)
325
+ item=v
326
+ #{inv}
327
+ end
328
+ end}
329
+
330
+ ret << %{def #{sym_short}_add(item)
331
+ if !item.nil?
332
+ #log.debug @#{sym}.size+1000
333
+ if @#{sym}.nil?
334
+ #log.debug "reset @#{sym}"
335
+ @#{sym}= ArrayOrSingleElement.new
336
+ end
337
+ #{sym_short}_typeOk?(item)
338
+ @#{sym}.push(item)
339
+ #{inv}
340
+ end
341
+ end}
342
+
343
+ return ret
344
+ end
345
+ end
346
+
347
+
348
+ module Mrdf_Model
349
+ def mtk_object_message
350
+ return ""
351
+ end
352
+ def mtk_related_message
353
+ return ""
354
+ end
355
+ end
356
+
357
+ module Mrdf_Resource
358
+ #return a string describing this object
359
+ #(used for error log messages)
360
+ def mtk_object_message
361
+ return <<END
362
+ ** uri =#{rdf_uri}
363
+ ** type=#{self.class.name}
364
+ ** to_s=#{self.to_s}
365
+ END
366
+ end
367
+ #return a string describing object related to this object
368
+ #(used for error log messages)
369
+ def mtk_related_message
370
+ related=""
371
+ ext_isReferencedBy.each { |g|
372
+ related=related+"** (#{g.class.name}) #{g}\n"
373
+ }
374
+ return related
375
+ end
376
+
377
+
378
+ # generates an error message used when
379
+ # "meth" returns unexpectedly no data.
380
+ def log_error_nil_one(meth)
381
+ return if log_already_displayed?("#{rdf_uri}__#{meth}")
382
+ log.error {
383
+
384
+ <<END
385
+ #{meth}_one nil for #{self}::#{self.class.name} (uri=#{rdf_uri})
386
+ ********* INVALID DATA DETECTED **********
387
+ ** This software expects the model element specified bellow
388
+ **#{mtk_object_message}
389
+ ** to have exactly one "#{meth}".
390
+ **
391
+ ** This is most likely caused by a missing data in source model.
392
+ ** Please check that previous element has a #{meth} defined.
393
+ **
394
+ ** This model element is related to these other model elements:
395
+ #{mtk_related_message}
396
+ ********* INVALID DATA DETECTED **********
397
+ END
398
+ }
399
+ raise Warning.new,"#{meth}_one nil null" if context[:failOnEmptyCallto_one,true]
400
+ end
401
+ end
402
+
403
+ #List of error message keys already displayed
404
+ MDA_LOG_ALREADY_DISPLAYED=Array.new
405
+
406
+ def log_already_displayed?(key)
407
+ return true if MDA_LOG_ALREADY_DISPLAYED.include?(key)
408
+ MDA_LOG_ALREADY_DISPLAYED<< key
409
+ return false
410
+ end