jrubyfx-fxmlloader-openjfx.patch 0.4.2-java

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.
@@ -0,0 +1,158 @@
1
+ # * Copyright (c) 2013 Patrick Plenefisch
2
+ # * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3
+ # *
4
+ # * This code is free software; you can redistribute it and/or modify it
5
+ # * under the terms of the GNU General Public License version 2 only, as
6
+ # * published by the Free Software Foundation. Oracle designates this
7
+ # * particular file as subject to the "Classpath" exception as provided
8
+ # * by Oracle in the LICENSE file that accompanied this code.
9
+ # *
10
+ # * This code is distributed in the hope that it will be useful, but WITHOUT
11
+ # * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
+ # * version 2 for more details (a copy is included in the LICENSE file that
14
+ # * accompanied this code).
15
+ # *
16
+ # * You should have received a copy of the GNU General Public License version
17
+ # * 2 along with this work; if not, write to the Free Software Foundation,
18
+ # * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
+ # *
20
+
21
+ require 'digest/sha1'
22
+ require 'fileutils'
23
+
24
+ def javafx
25
+ Java::javafx
26
+ end
27
+
28
+ Infinity = 1.0/0.0
29
+
30
+ class FxmlJitInfo
31
+ include JRubyFX
32
+ def self.hash(file)
33
+ Digest::SHA1.hexdigest(File.read file)
34
+ end
35
+ def self.load_aot(file, cache, validate = true)
36
+ if validate
37
+ hash = hash(file)
38
+ f_hash = File.open(cache, "r", &:readline).strip
39
+ return false if "# #{hash} encoding: utf-8" != f_hash
40
+ end
41
+ hash = Digest::SHA1.hexdigest(File.basename file)
42
+ require cache
43
+ JRubyFX::GeneratedAssets.const_get("AOT#{hash}").new rescue nil
44
+ end
45
+ # TODO: store jit settings in here instead of $RB_* variables
46
+ attr_accessor :file_name, :raw_code, :jit_settings
47
+ def initialize(file_name, jit_settings=1, outfile=nil, cache_dir=nil,validate = true, opts = nil)
48
+ @file_name = file_name
49
+ @no_write = (opts && opts[:no_write]) || false
50
+ if @file_name.start_with? "file:"
51
+ @file_name = @file_name.gsub(/^file\:/, '')
52
+ elsif @file_name.start_with? "jar:"
53
+ @no_write = true
54
+ elsif @file_name.start_with? "compoundjar:"
55
+ @no_write = true
56
+ end
57
+ @jit_settings = jit_settings
58
+ @run_count = 0
59
+ @opts = opts
60
+ @outfile = if @outfile
61
+ outfile
62
+ else
63
+ cache_dir = cache_dir || File.join(File.dirname(@file_name), ".jrubyfx_cache")
64
+ FileUtils.mkpath(cache_dir) unless File.directory?(cache_dir) or @no_write
65
+ @f_hash = Digest::SHA1.hexdigest(File.basename @file_name)
66
+ File.join(cache_dir, "#{@f_hash}.rb")
67
+ end
68
+ if File.exist?(@outfile) && !(opts && opts[:force])
69
+ @compiled = self.class.load_aot(@file_name, @outfile, validate)
70
+ if @compiled
71
+ dputs "got #{file_name} from cache"
72
+ end
73
+ end
74
+ end
75
+ def hash
76
+ FxmlJitInfo.hash(@file_name)
77
+ end
78
+ def should_jit?
79
+ return false if @jit_settings == :no_jit || compiled?
80
+ return true if (@run_count += 1) >= @jit_settings
81
+ end
82
+ def compiled?
83
+ !!@compiled
84
+ end
85
+ def decompile
86
+ @compiled = nil
87
+ end
88
+ def __build_via_jit(__local_fxml_controller, __local_namespace, __local_jruby_ext)
89
+ @compiled.__build_via_jit(__local_fxml_controller, __local_namespace, __local_jruby_ext)
90
+ end
91
+ def compile(code=@raw_code)
92
+ @raw_code = code
93
+ # TODO: begin rescue end
94
+ full_code = <<METHOD_DEF
95
+ def __build_via_jit(__local_fxml_controller, __local_namespace, __local_jruby_ext)
96
+ __local_fx_id_setter = lambda do |name, __i|
97
+ __local_namespace[name] = __i
98
+ __local_fxml_controller.instance_variable_set(("@\#{name}").to_sym, __i)
99
+ end
100
+ #{code}
101
+ end
102
+ METHOD_DEF
103
+ ;#)
104
+ unless @no_write
105
+ begin
106
+ jit_aot_cache(full_code)
107
+ rescue
108
+ p $!
109
+ jit_no_cache(full_code)
110
+ end
111
+ else
112
+ jit_no_cache(full_code)
113
+ end
114
+ if @opts && @opts[:compiled_hook]
115
+ @opts[:compiled_hook].call(@outfile)
116
+ end
117
+
118
+ end
119
+
120
+ def jit_no_cache(full_code)
121
+ dputs "JIT only, no aot for #{@file_name}"
122
+ self.instance_eval full_code
123
+ @compiled = true
124
+ end
125
+
126
+ def jit_aot_cache(full_code)
127
+ File.open(@outfile, "w") do |f|
128
+ hash = hash()
129
+ f << <<AOT
130
+ # #{hash} encoding: utf-8
131
+ # @@ 1
132
+
133
+ ########################### DO NOT MODIFY THIS FILE ###########################
134
+ # This file was automatically generated by JRubyFX-fxmlloader on #
135
+ # #{Time.now} for #{@file_name}
136
+ ########################### DO NOT MODIFY THIS FILE ###########################
137
+
138
+ module JRubyFX
139
+ module GeneratedAssets
140
+ class AOT#{@f_hash}
141
+ include JRubyFX
142
+ #{full_code}
143
+ def hash
144
+ #{hash.inspect}
145
+ end
146
+ def compiled?
147
+ true
148
+ end
149
+ end
150
+ end
151
+ end
152
+ AOT
153
+ end
154
+ puts "saved #{@outfile} to cache"
155
+ require @outfile
156
+ @compiled = JRubyFX::GeneratedAssets.const_get("AOT#{@f_hash}").new rescue nil
157
+ end
158
+ end
@@ -0,0 +1,290 @@
1
+ #/*
2
+ # * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3
+ # * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
+ # *
5
+ # * This code is free software; you can redistribute it and/or modify it
6
+ # * under the terms of the GNU General Public License version 2 only, as
7
+ # * published by the Free Software Foundation. Oracle designates this
8
+ # * particular file as subject to the "Classpath" exception as provided
9
+ # * by Oracle in the LICENSE file that accompanied this code.
10
+ # *
11
+ # * This code is distributed in the hope that it will be useful, but WITHOUT
12
+ # * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ # * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
+ # * version 2 for more details (a copy is included in the LICENSE file that
15
+ # * accompanied this code).
16
+ # *
17
+ # * You should have received a copy of the GNU General Public License version
18
+ # * 2 along with this work; if not, write to the Free Software Foundation,
19
+ # * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
+ # *
21
+ # * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
+ # * or visit www.oracle.com if you need additional information or have any
23
+ # * questions.
24
+ # */
25
+
26
+
27
+ #/**
28
+ # * Class representing an observable expression value.
29
+ # */
30
+ class RRExpressionValue < Java::javafx.beans.value.ObservableValueBase
31
+ #// Monitors a namespace for changes along a key path
32
+
33
+
34
+
35
+ def initialize(namespace, expression, type)
36
+ super()
37
+ if (namespace == nil)
38
+ raise "NullPointerException.new();"
39
+ end
40
+
41
+ if (expression == nil)
42
+ raise "NullPointerException.new();"
43
+ end
44
+
45
+ if (type == nil)
46
+ raise "NullPointerException.new();"
47
+ end
48
+
49
+ @listenerCount = 0;
50
+
51
+ @namespace = namespace;
52
+ @expression = expression;
53
+ @type = type;
54
+
55
+ arguments = expression.getArguments();
56
+ @argumentMonitors = java.util.ArrayList.new(arguments.size());
57
+
58
+ for argument in arguments
59
+ @argumentMonitors.add(KeyPathMonitor.new(self, argument.iterator()));
60
+ end
61
+ end
62
+
63
+
64
+ def getValue()
65
+ return RubyWrapperBeanAdapter.coerce(@expression.evaluate(@namespace), @type);
66
+ end
67
+
68
+ def addListener( listener)
69
+ if (@listenerCount == 0)
70
+ monitorArguments();
71
+ end
72
+
73
+ super(listener);
74
+ @listenerCount += 1
75
+ end
76
+
77
+ def removeListener( listener)
78
+ super(listener);
79
+ @listenerCount-=1
80
+
81
+ if (@listenerCount == 0)
82
+ unmonitorArguments();
83
+ end
84
+ end
85
+
86
+ def monitorArguments()
87
+ for argumentMonitor in @argumentMonitors
88
+ argumentMonitor.monitor(@namespace);
89
+ end
90
+ end
91
+
92
+ def unmonitorArguments()
93
+ for argumentMonitor in @argumentMonitors
94
+ argumentMonitor.unmonitor();
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ class KeyPathMonitor
101
+ @key = nil;
102
+ @next = nil
103
+
104
+ @namespace = nil;
105
+
106
+
107
+ class ListChangeImpl
108
+ include ListChangeListener
109
+
110
+ def initialize(this)
111
+ @this = this
112
+ end
113
+
114
+ def onChanged(change)
115
+ @this.list_changed(change)
116
+ end
117
+ end
118
+
119
+
120
+ class MapChangeImpl
121
+ include MapChangeListener
122
+
123
+ def initialize(this)
124
+ @this = this
125
+ end
126
+
127
+ def onChanged(change)
128
+ @this.map_changed(change)
129
+ end
130
+ end
131
+
132
+
133
+
134
+ class ChangeListenerImpl
135
+ include ChangeListener
136
+
137
+ def initialize(this)
138
+ @this = this
139
+ end
140
+
141
+ def changed(ov, old, new)
142
+ @this.normal_changed(ov, old, new)
143
+ end
144
+ end
145
+
146
+ def initialize(this, keyPathIterator)
147
+ @key = keyPathIterator.next();
148
+ @this = this
149
+
150
+
151
+ @listChangeListener = ListChangeImpl.new(self)
152
+
153
+
154
+ @mapChangeListener = MapChangeImpl.new(self)
155
+
156
+
157
+ @propertyChangeListener = ChangeListenerImpl.new(self)
158
+
159
+ if (keyPathIterator.hasNext())
160
+ @next = KeyPathMonitor.new(this, keyPathIterator);
161
+ else
162
+ @next = nil;
163
+ end
164
+ end
165
+
166
+ def list_changed(change)
167
+ while (change.next())
168
+ index = @key.to_i
169
+
170
+ if (index >= change.getFrom() && index < change.getTo())
171
+ @this.fireValueChangedEvent();
172
+ remonitor();
173
+ end
174
+ end
175
+ end
176
+
177
+ def map_changed(change)
178
+ if (@key == (change.getKey()))
179
+ @this.fireValueChangedEvent();
180
+ remonitor();
181
+ end
182
+ end
183
+
184
+ def normal_changed(observable, oldValue, newValue)
185
+ if (@key == (observable.getName()))
186
+
187
+ @this.fireValueChangedEvent();
188
+ remonitor();
189
+ end
190
+ end
191
+
192
+ def monitor(namespace)
193
+ if (namespace.is_a? ObservableList)
194
+ old_verbose = $VERBOSE
195
+ begin
196
+ $VERBOSE = nil
197
+ namespace.addListener @listChangeListener
198
+ ensure
199
+ # always re-set to old value, even if block raises an exception
200
+ $VERBOSE = old_verbose
201
+ end
202
+ elsif (namespace.is_a? ObservableMap)
203
+ old_verbose = $VERBOSE
204
+ begin
205
+ $VERBOSE = nil
206
+ namespace.addListener @mapChangeListener
207
+ ensure
208
+ # always re-set to old value, even if block raises an exception
209
+ $VERBOSE = old_verbose
210
+ end
211
+ else
212
+ namespaceAdapter = RubyWrapperBeanAdapter.for(namespace);
213
+ propertyModel = namespaceAdapter.getPropertyModel(@key).to_java
214
+ if (propertyModel != nil)
215
+ old_verbose = $VERBOSE
216
+ begin
217
+ $VERBOSE = nil
218
+ propertyModel.addListener @propertyChangeListener
219
+ ensure
220
+ # always re-set to old value, even if block raises an exception
221
+ $VERBOSE = old_verbose
222
+ end
223
+ end
224
+
225
+ @namespace = namespaceAdapter;
226
+ end
227
+
228
+ @namespace = namespace;
229
+
230
+ if (@next != nil)
231
+ value = Expression.get(@namespace, @key)
232
+ if (value != nil)
233
+ @next.monitor(value);
234
+ end
235
+ end
236
+ end
237
+
238
+ def unmonitor()
239
+ if (@namespace.is_a? ObservableList)
240
+ old_verbose = $VERBOSE
241
+ begin
242
+ $VERBOSE = nil
243
+ @namespace.removeListener @listChangeListener
244
+ ensure
245
+ # always re-set to old value, even if block raises an exception
246
+ $VERBOSE = old_verbose
247
+ end
248
+ elsif (@namespace.is_a? ObservableMap)
249
+ old_verbose = $VERBOSE
250
+ begin
251
+ $VERBOSE = nil
252
+ @namespace.removeListener @mapChangeListener
253
+ ensure
254
+ # always re-set to old value, even if block raises an exception
255
+ $VERBOSE = old_verbose
256
+ end
257
+ elsif (@namespace != nil)
258
+ namespaceAdapter = @namespace;
259
+ propertyModel = namespaceAdapter.getPropertyModel(@key);
260
+
261
+ if (propertyModel != nil)
262
+ old_verbose = $VERBOSE
263
+ begin
264
+ $VERBOSE = nil
265
+ propertyModel.removeListener @propertyChangeListener
266
+ ensure
267
+ # always re-set to old value, even if block raises an exception
268
+ $VERBOSE = old_verbose
269
+ end
270
+ end
271
+ end
272
+
273
+ @namespace = nil;
274
+
275
+ if (@next != nil)
276
+ @next.unmonitor();
277
+ end
278
+ end
279
+
280
+ def remonitor()
281
+ if (@next != nil)
282
+ @next.unmonitor();
283
+ value = Expression.get(@namespace, @key);
284
+ if (value != nil)
285
+ @next.monitor(value);
286
+ end
287
+ end
288
+ end
289
+ end
290
+
@@ -0,0 +1,708 @@
1
+ class OBJFXBuilderWrapper < Java::java.util.AbstractMap
2
+ include Java::javafx.util.Builder
3
+ def initialize(safeobj, type)
4
+ super()
5
+ @type = type
6
+ @obj = safeobj
7
+ end
8
+
9
+ def wrapped_class
10
+ @type
11
+ end
12
+
13
+ def on_put(&on_put)
14
+ @on_put = on_put
15
+ end
16
+
17
+ def build
18
+ @obj.build.tap{|x| rmorph self, x}
19
+ end
20
+
21
+ def containsKey(o)
22
+ @obj.containsKey(o)
23
+ end
24
+
25
+ def get(o)
26
+ @obj.get(o)
27
+ end
28
+
29
+ def put(k, v)
30
+ @on_put.call(k, v) if @on_put
31
+ @obj.put(k, v)
32
+ end
33
+
34
+ def [](o)
35
+ get(o)
36
+ end
37
+ def []=(k, v)
38
+ put(k, v)
39
+ end
40
+
41
+ def entrySet
42
+ java.util.HashMap.new({}).entrySet
43
+ end
44
+
45
+ def ==(rhs)
46
+ self.equal? rhs # do pointer comparison
47
+ end
48
+
49
+ def inspect
50
+ "#<ObjectBuilderWrapper:#{self.object_id.to_s 16} type=#{@type}, child=#{@obj.class.inspect}>"
51
+ end
52
+ end
53
+
54
+ class InstanceDeclarationElement < ValueElement
55
+ attr_accessor :type, :constant, :factory
56
+
57
+ def initialize(current, xmlStreamReader, loadListener, parentLoader, type)
58
+ super(current, xmlStreamReader, loadListener, parentLoader)
59
+ @type = type;
60
+ @constant = nil;
61
+ @factory = nil;
62
+ end
63
+
64
+ def processAttribute( prefix, localName, value)
65
+ if (prefix != nil && prefix == (FXL::FX_NAMESPACE_PREFIX))
66
+ if (localName == (FXL::FX_VALUE_ATTRIBUTE))
67
+ @value = value;
68
+ elsif (localName == (FXL::FX_CONSTANT_ATTRIBUTE))
69
+ @constant = value;
70
+ elsif (localName == (FXL::FX_FACTORY_ATTRIBUTE))
71
+ @factory = value;
72
+ else
73
+ super(prefix, localName, value);
74
+ end
75
+ else
76
+ super(prefix, localName, value);
77
+ end
78
+ end
79
+
80
+ def constructValue()
81
+ value = nil
82
+ if (@value != nil)
83
+ value = RubyWrapperBeanAdapter.coerce(@value, type);
84
+ elsif (constant != nil)
85
+ value = RubyWrapperBeanAdapter.getConstantValue(type, constant);
86
+ elsif (factory != nil)
87
+ factoryMethod = nil
88
+ begin
89
+ factoryMethod = MethodUtil.getMethod(type, factory, []);
90
+ rescue NoSuchMethodException => exception
91
+ raise LoadException.new(exception);
92
+ end
93
+
94
+ begin
95
+ value = MethodUtil.invoke(factoryMethod, nil, []);
96
+ rescue IllegalAccessException => exception
97
+ raise LoadException.new(exception);
98
+ rescue InvocationTargetException => exception
99
+ raise LoadException.new(exception);
100
+ end
101
+ else
102
+ value = (parentLoader.builderFactory == nil) ? nil : parentLoader.builderFactory.getBuilder(type);
103
+ if (value.is_a? Builder or (value.respond_to?(:java_object) && value.java_object.is_a?(Builder)))
104
+ begin
105
+ value.size
106
+ rescue java.lang.UnsupportedOperationException => ex
107
+ dputs "########################## WARNING #############################3"
108
+ value = OBJFXBuilderWrapper.new(value, type)
109
+ value.on_put {|k, v| rctor value, k, v }
110
+ end
111
+ end
112
+ if (value == nil)
113
+ begin
114
+ #TODO: does this work?
115
+ value = type.ruby_class.new
116
+ rescue InstantiationException => exception
117
+ raise LoadException.new(exception);
118
+ rescue IllegalAccessException => exception
119
+ raise LoadException.new(exception);
120
+ end
121
+ else
122
+ end
123
+ end
124
+ if factory
125
+ rputs value, "build(FactoryBuilderBuilder, #{type.ruby_class}, #{factory.inspect}) do"
126
+ elsif @value
127
+ rno_show(value)
128
+ rputs value, value.inspect
129
+ else
130
+ rputs value, "build(#{type.ruby_class}) do"
131
+ end
132
+ rnest 1
133
+ return value;
134
+ end
135
+ end
136
+
137
+ # Element representing an unknown type
138
+ class UnknownTypeElement < ValueElement
139
+
140
+ def initialize()
141
+ dputs "oh no...."
142
+ end
143
+ # TODO: cleanup
144
+ # Map type representing an unknown value
145
+ # def UnknownValueMap extends AbstractMap<String, Object>
146
+ # def<?> items = ArrayList.new<Object>();
147
+ # def<String, Object> values = HashMap.new<String, Object>();
148
+ #
149
+ # def get(Object key)
150
+ # if (key == nil)
151
+ # raise NullPointerException.new();
152
+ # end
153
+ #
154
+ # return (key == (java_class().getAnnotation(DefaultProperty.java_class).value()))
155
+ # ? items : values.get(key);
156
+ # end
157
+ #
158
+ # def put(String key, Object value)
159
+ # if (key == nil)
160
+ # raise NullPointerException.new();
161
+ # end
162
+ #
163
+ # if (key == (java_class().getAnnotation(DefaultProperty.java_class).value()))
164
+ # raise IllegalArgumentException.new();
165
+ # end
166
+ #
167
+ # return values.put(key, value);
168
+ # end
169
+ #
170
+ # def entrySet()
171
+ # return Collections.emptySet();
172
+ # end
173
+ # end
174
+
175
+ def processEndElement()
176
+ # No-op
177
+ end
178
+
179
+ def constructValue()
180
+ return UnknownValueMap.new();
181
+ end
182
+ end
183
+
184
+ # Element representing an include
185
+ class IncludeElement < ValueElement
186
+ # TODO: cleanup
187
+ attr_accessor :source, :resources, :charset
188
+ def initialize(current, xmlStreamReader, loadListener, parentLoader)
189
+ super
190
+ @source = nil;
191
+ @resources = parentLoader.resources;
192
+ @charset = parentLoader.charset;
193
+ end
194
+
195
+ def processAttribute(prefix, localName, value)
196
+
197
+ if (prefix == nil)
198
+ if (localName == (FXL::INCLUDE_SOURCE_ATTRIBUTE))
199
+ if (loadListener != nil)
200
+ loadListener.readInternalAttribute(localName, value);
201
+ end
202
+
203
+ source = value;
204
+ elsif (localName == (FXL::INCLUDE_RESOURCES_ATTRIBUTE))
205
+ if (loadListener != nil)
206
+ loadListener.readInternalAttribute(localName, value);
207
+ end
208
+
209
+ resources = ResourceBundle.getBundle(value, Locale.getDefault(),
210
+ parentLoader.resources.java_class().getClassLoader());
211
+ elsif (localName == (FXL::INCLUDE_CHARSET_ATTRIBUTE))
212
+ if (loadListener != nil)
213
+ loadListener.readInternalAttribute(localName, value);
214
+ end
215
+
216
+ charset = Charset.forName(value);
217
+ else
218
+ super(prefix, localName, value);
219
+ end
220
+ else
221
+ super(prefix, localName, value);
222
+ end
223
+ end
224
+
225
+ def constructValue()
226
+ if (source == nil)
227
+ raise LoadException.new(FXL::INCLUDE_SOURCE_ATTRIBUTE + " is required.");
228
+ end
229
+
230
+ location = nil
231
+ if (source[0] == '/')
232
+ location = classLoader.getResource(source[1..-1]);
233
+ else
234
+ if (location == nil)
235
+ raise LoadException.new("Base location is undefined.");
236
+ end
237
+
238
+ location = URL.new(location, source);
239
+ end
240
+
241
+ fxmlLoader = FxmlLoader.new(location, controller, resources,
242
+ parentLoader.builderFactory, charset,
243
+ loaders);
244
+ fxmlLoader.parentLoader = parentSelf
245
+
246
+ if (isCyclic(parentSelf, fxmlLoader))
247
+ raise IOException.new(
248
+ String.format(
249
+ "Including \"%s\" in \"%s\" created cyclic reference.",
250
+ fxmlLoader.location.toExternalForm(),
251
+ parentSelf.location.toExternalForm()));
252
+ end
253
+ fxmlLoader.setClassLoader(classLoader);
254
+ fxmlLoader.setStaticLoad(staticLoad);
255
+
256
+ value = fxmlLoader.load();
257
+
258
+ if (fx_id != nil)
259
+ id = fx_id + FXL::CONTROLLER_SUFFIX;
260
+ controller = fxmlLoader.getController();
261
+
262
+ namespace.put(id, controller);
263
+
264
+ if (parentLoader.controller != nil)
265
+ field = getControllerFields().get(id);
266
+
267
+ if (field != nil)
268
+ begin
269
+ field.set(parentLoader.controller, controller);
270
+ rescue IllegalAccessException => exception
271
+ raise LoadException.new(exception);
272
+ end
273
+ end
274
+ end
275
+ end
276
+
277
+ return value;
278
+ end
279
+ end
280
+
281
+ # Element representing a reference
282
+ class ReferenceElement < ValueElement
283
+ attr_accessor :source
284
+ @source = nil;
285
+
286
+ def processAttribute(prefix, localName, value)
287
+ if (prefix == nil)
288
+ if (localName == (FXL::REFERENCE_SOURCE_ATTRIBUTE))
289
+ if (loadListener != nil)
290
+ loadListener.readInternalAttribute(localName, value);
291
+ end
292
+ @source = value;
293
+ else
294
+ super(prefix, localName, value);
295
+ end
296
+ else
297
+ super(prefix, localName, value);
298
+ end
299
+ end
300
+
301
+ def constructValue()
302
+ if (source == nil)
303
+ raise LoadException.new(FXL::REFERENCE_SOURCE_ATTRIBUTE + " is required.");
304
+ end
305
+
306
+ path = KeyPath.parse(source);
307
+ if (!Expression.isDefined(parentLoader.namespace, path))
308
+ raise LoadException.new("Value \"" + source + "\" does not exist.");
309
+ end
310
+
311
+ return Expression.get(parentLoader.namespace, path);
312
+ end
313
+ end
314
+
315
+ # Element representing a copy
316
+ class CopyElement < ValueElement
317
+ attr_accessor :source
318
+ @source = nil;
319
+
320
+ def processAttribute(prefix, localName, value)
321
+
322
+ if (prefix == nil)
323
+ if (localName == (FXL::COPY_SOURCE_ATTRIBUTE))
324
+ if (loadListener != nil)
325
+ loadListener.readInternalAttribute(localName, value);
326
+ end
327
+
328
+ @source = value;
329
+ else
330
+ super(prefix, localName, value);
331
+ end
332
+ else
333
+ super(prefix, localName, value);
334
+ end
335
+ end
336
+
337
+ def constructValue()
338
+ if (source == nil)
339
+ raise LoadException.new(FXL::COPY_SOURCE_ATTRIBUTE + " is required.");
340
+ end
341
+
342
+ path = KeyPath.parse(source);
343
+ if (!Expression.isDefined(namespace, path))
344
+ raise LoadException.new("Value \"" + source + "\" does not exist.");
345
+ end
346
+
347
+ sourceValue = Expression.get(namespace, path);
348
+ sourceValueType = sourceValue.java_class();
349
+
350
+ constructor = nil;
351
+ begin
352
+ constructor = ConstructorUtil.getConstructor(sourceValueType, [sourceValueType]);
353
+ rescue NoSuchMethodException => exception
354
+ # No-op
355
+ end
356
+
357
+ value=nil
358
+ if (constructor != nil)
359
+ begin
360
+ #TODO: try to do evil things here
361
+ ReflectUtil.checkPackageAccess(sourceValueType);
362
+ value = constructor.newInstance(sourceValue);
363
+ rescue InstantiationException => exception
364
+ raise LoadException.new(exception);
365
+ rescue IllegalAccessException => exception
366
+ raise LoadException.new(exception);
367
+ rescue InvocationTargetException => exception
368
+ raise LoadException.new(exception);
369
+ end
370
+ else
371
+ raise LoadException.new("Can't copy value " + sourceValue + ".");
372
+ end
373
+
374
+ return value;
375
+ end
376
+ end
377
+
378
+ # Element representing a predefined root value
379
+ class RootElement < ValueElement
380
+ @type = nil
381
+
382
+ def processAttribute( prefix, localName, value)
383
+
384
+ if (prefix == nil)
385
+ if (localName == (FXL::ROOT_TYPE_ATTRIBUTE))
386
+ if (loadListener != nil)
387
+ loadListener.readInternalAttribute(localName, value);
388
+ end
389
+
390
+ @type = value;
391
+ else
392
+ super(prefix, localName, value);
393
+ end
394
+ else
395
+ super(prefix, localName, value);
396
+ end
397
+ end
398
+
399
+ def constructValue()
400
+ if (@type == nil)
401
+ raise LoadException.new(FXL::ROOT_TYPE_ATTRIBUTE + " is required.");
402
+ end
403
+
404
+ type = parentLoader.getType(@type);
405
+
406
+ if (type == nil)
407
+ raise LoadException.new(@type + " is not a valid type.");
408
+ end
409
+
410
+ value=nil
411
+ root = parentLoader.root
412
+ if (root == nil)
413
+ if $JRUBYFX_AOT_COMPILING
414
+ root = parentLoader.root = type.ruby_class.new
415
+ value = root
416
+ else
417
+ raise LoadException.new("Root hasn't been set. Use method setRoot() before load.");
418
+ end
419
+ else
420
+ if (!type.isAssignableFrom(root.java_class()))
421
+ raise LoadException.new("Root is not an instance of " + type.getName() + ".");
422
+ end
423
+
424
+ value = root;
425
+ end
426
+ rputs value, "with(__local_fxml_controller) do"
427
+ rnest 1
428
+ return value;
429
+ end
430
+ end
431
+
432
+ # Element representing a property
433
+ class PropertyElement < Element
434
+ attr_accessor :name, :sourceType, :readOnly
435
+
436
+ def initialize(current, xmlStreamReader, loadListener, parentLoader, name, sourceType)
437
+
438
+ @name = nil
439
+ @sourceType = nil
440
+ @readOnly = nil
441
+ super(current, xmlStreamReader, loadListener, parentLoader)
442
+ if (parent == nil)
443
+ raise LoadException.new("Invalid root element.");
444
+ end
445
+
446
+ if (parent.value == nil)
447
+ raise LoadException.new("Parent element does not support property elements.");
448
+ end
449
+
450
+ @name = name;
451
+ @sourceType = sourceType;
452
+
453
+ if (sourceType == nil)
454
+ # The element represents an instance property
455
+ if (name.start_with?(FXL::EVENT_HANDLER_PREFIX))
456
+ raise LoadException.new("\"" + name + "\" is not a valid element name.");
457
+ end
458
+
459
+ parentProperties = parent.getProperties();
460
+ if (parent.isTyped())
461
+ @readOnly = parent.getValueAdapter().read_only?(name);
462
+ else
463
+ # If the map already defines a value for the property, assume
464
+ # that it is read-only
465
+ @readOnly = parentProperties.has_key?(name);
466
+ end
467
+
468
+ if (@readOnly)
469
+ value = parentProperties[name]
470
+ if (value == nil)
471
+ raise LoadException.new("Invalid property.");
472
+ end
473
+ updateValue(value);
474
+ end
475
+ else
476
+ # The element represents a static property
477
+ @readOnly = false;
478
+ end
479
+ end
480
+
481
+ def isCollection()
482
+ return (@readOnly) ? super() : false;
483
+ end
484
+
485
+ def add( element)
486
+ @pushd = true
487
+ rp = nil
488
+ # Coerce the element to the list item type
489
+ if (parent.isTyped())
490
+ listType = parent.getValueAdapter().getGenericType(name);
491
+ lit = RubyWrapperBeanAdapter.getListItemType(listType)
492
+ # FIXME: HACK!
493
+ if element.class.inspect == "Java::JavaNet::URL"
494
+ lit = Java::java.lang.String.java_class
495
+ rp = rget(element).match(/build\(FxmlBuilderBuilder, \{"value"=>(.*)\}, Java::JavaNet::URL\) do\n( )*end/)[1]
496
+ end
497
+ element = RubyWrapperBeanAdapter.coerce(element, lit);
498
+ end
499
+
500
+ # Add the item to the list
501
+ super(element, name, rp);
502
+ end
503
+
504
+ def set( value)
505
+ @pushd = true
506
+ # Update the value
507
+ updateValue(value);
508
+
509
+ if (sourceType == nil)
510
+ # Apply value to parent element's properties
511
+ parent.getProperties[name] = value
512
+ else
513
+ if (parent.value.is_a? Builder)
514
+ # Defer evaluation of the property
515
+ parent.staticPropertyElements.add(self);
516
+ else
517
+ # Apply the static property value
518
+ RubyWrapperBeanAdapter.put3(parent.value, sourceType, name, value);
519
+ end
520
+ end
521
+ end
522
+
523
+ def processAttribute( prefix, localName, value)
524
+ if (!readOnly)
525
+ raise LoadException.new("Attributes are not supported for writable property elements.");
526
+ end
527
+
528
+ super(prefix, localName, value);
529
+ end
530
+
531
+ def processEndElement()
532
+ super();
533
+ if (readOnly)
534
+ processInstancePropertyAttributes();
535
+ processEventHandlerAttributes();
536
+ unless @pushd
537
+ rputs parent.value, "with(get#{@name[0].upcase}#{@name[1..-1]}) do\n#{rget(@value)||@value.inspect}\nend" unless parent.value == @value
538
+ end
539
+ end
540
+ end
541
+
542
+ def processCharacters()
543
+ if (!readOnly)
544
+ text = xmlStreamReader.getText();
545
+ #TODO: normal regexes
546
+ text = extraneousWhitespacePattern.matcher(text).replaceAll(" ");
547
+
548
+ set(text.strip());
549
+ else
550
+ super();
551
+ end
552
+ end
553
+ end
554
+
555
+ # Element representing an unknown static property
556
+ class UnknownStaticPropertyElement < Element
557
+ def initialize
558
+ if (parent == nil)
559
+ raise LoadException.new("Invalid root element.");
560
+ end
561
+
562
+ if (parent.value == nil)
563
+ raise LoadException.new("Parent element does not support property elements.");
564
+ end
565
+ end
566
+
567
+ def isCollection()
568
+ return false;
569
+ end
570
+
571
+ def set( value)
572
+ updateValue(value);
573
+ end
574
+
575
+ def processCharacters()
576
+ text = xmlStreamReader.getText();
577
+ # TODO: REGEX!
578
+ text = extraneousWhitespacePattern.matcher(text).replaceAll(" ");
579
+
580
+ updateValue(text.strip());
581
+ end
582
+ end
583
+
584
+ # Element representing a script block
585
+ class ScriptElement < Element
586
+ def initialize(current, xmlStreamReader, loadListener, parentLoader)
587
+ super
588
+ @source = nil;
589
+ @charset = parentLoader.charset;
590
+ end
591
+
592
+ def isCollection()
593
+ return false;
594
+ end
595
+
596
+ def processStartElement()
597
+ super();
598
+
599
+ if (@source != nil && !staticLoad)
600
+ i = @source.rindex(".");
601
+ if (i == nil)
602
+ raise ("Cannot determine type of script \"" + @source + "\".");
603
+ end
604
+ extension = @source[(i + 1)..-1];
605
+ scriptEngine = nil
606
+ #TODO: use JRUBY stuff
607
+ oldLoader = Thread.currentThread().getContextClassLoader();
608
+ begin
609
+ Thread.currentThread().setContextClassLoader(classLoader);
610
+ scriptEngineManager = getScriptEngineManager();
611
+ scriptEngine = scriptEngineManager.getEngineByExtension(extension);
612
+ ensure
613
+ Thread.currentThread().setContextClassLoader(oldLoader);
614
+ end
615
+
616
+ if (scriptEngine == nil)
617
+ raise ("Unable to locate scripting engine for" + " extension " + extension + ".");
618
+ end
619
+
620
+ scriptEngine.setBindings(scriptEngineManager.getBindings(), ScriptContext.ENGINE_SCOPE);
621
+
622
+ begin
623
+ location = nil
624
+ if (@source[0] == '/')
625
+ location = classLoader.getResource(@source[(1)..-1]);
626
+ else
627
+ if (parentLoader.location == nil)
628
+ raise LoadException.new("Base location is undefined.");
629
+ end
630
+
631
+ location = URL.new(parentLoader.location, @source);
632
+ end
633
+
634
+ InputStreamReader scriptReader = nil;
635
+ begin
636
+ scriptReader = InputStreamReader.new(location.openStream(), @charset);
637
+ scriptEngine.eval(scriptReader);
638
+ rescue ScriptException => exception
639
+ exception.printStackTrace();
640
+ ensure
641
+ if (scriptReader != nil)
642
+ scriptReader.close();
643
+ end
644
+ end
645
+ rescue IOException => exception
646
+ raise LoadException.new(exception);
647
+ end
648
+ end
649
+ end
650
+
651
+ def processEndElement()
652
+ super();
653
+ if (value != nil && !parentLoader.staticLoad)
654
+ # Evaluate the script
655
+ begin
656
+ rputs nil, "__local_sem_lang_inst_#{rget_sem(parentLoader.scriptEngine)}.eval(#{value.to_s.inspect})"
657
+ parentLoader.scriptEngine.eval( value.to_s);
658
+ rescue ScriptException => exception
659
+ STDERR.puts (exception.getMessage());
660
+ end
661
+ end
662
+ end
663
+
664
+ def processCharacters()
665
+ if (@source != nil)
666
+ raise LoadException.new("Script source already specified.");
667
+ end
668
+
669
+ if (parentLoader.scriptEngine == nil && !parentLoader.staticLoad)
670
+ raise LoadException.new("Page language not specified.");
671
+ end
672
+ updateValue(xmlStreamReader.getText());
673
+ end
674
+
675
+ def processAttribute(prefix, localName, value)
676
+ if (prefix == nil && localName == (FXL::SCRIPT_SOURCE_ATTRIBUTE))
677
+ if (loadListener != nil)
678
+ loadListener.readInternalAttribute(localName, value);
679
+ end
680
+
681
+ @source = value;
682
+ elsif (localName == (FXL::SCRIPT_CHARSET_ATTRIBUTE))
683
+ if (loadListener != nil)
684
+ loadListener.readInternalAttribute(localName, value);
685
+ end
686
+
687
+ @charset = Charset.forName(value);
688
+ else
689
+ raise LoadException.new(prefix == nil ? localName : prefix + ":" + localName + " is not a valid attribute.");
690
+ end
691
+ end
692
+ end
693
+
694
+ # Element representing a define block
695
+ class DefineElement < Element
696
+ def isCollection()
697
+ return true;
698
+ end
699
+
700
+ def add(element)
701
+ rputs parent.value, rget(element)
702
+ # No-op
703
+ end
704
+
705
+ def processAttribute(prefix, localName, value)
706
+ raise LoadException.new("Element does not support attributes.");
707
+ end
708
+ end