Module: Ruboto::Util::Build

Includes:
Verify
Included in:
Update
Defined in:
lib/ruboto/util/build.rb

Constant Summary collapse

SCRIPTS_DIR =
'src'

Constants included from Verify

Verify::ON_TRAVIS

Instance Method Summary collapse

Methods included from Verify

#project_api_level, #project_properties, #save_manifest, #save_ruboto_config, #save_test_manifest, #verify_activity, #verify_api, #verify_manifest, #verify_min_sdk, #verify_package, #verify_project_properties, #verify_ruboto_config, #verify_sdk_versions, #verify_strings, #verify_target_sdk, #verify_test_manifest

Instance Method Details

#build_file(src, package, name, substitutions, dest = '.') ⇒ Object

build_file: Reads the src from the appropriate location,

uses the substitutions hash to modify the contents,
and writes to the new location

17
18
19
20
21
22
23
24
25
# File 'lib/ruboto/util/build.rb', line 17

def build_file(src, package, name, substitutions, dest='.')
  to = File.join(dest, "src/#{package.gsub('.', '/')}")
  Dir.mkdir(to) unless File.directory?(to)

  text = File.read(File.expand_path(Ruboto::GEM_ROOT + "/assets/src/#{src}.java"))
  substitutions.each { |k, v| text.gsub!(k, v) }

  File.open(File.join(to, "#{name}.java"), 'w') { |f| f << text }
end

#check_methods(methods, force = nil) ⇒ Object

check_methods: Checks the methods to see if they are available for all api levels


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/ruboto/util/build.rb', line 50

def check_methods(methods, force=nil)
  min_api = verify_min_sdk.to_i
  target_api = verify_target_sdk.to_i

  # Remove methods changed outside of the scope of the sdk versions
  methods = methods.select { |i| !i.attribute('api_added') || (i.attribute('api_added').to_i <= target_api) }
  # methods = methods.select{|i| !i.attribute('deprecated') || (i.attribute('deprecated').to_i > min_api)}
  methods = methods.select { |i| !i.attribute('api_removed') || (i.attribute('api_removed').to_i > min_api) }

  # Inform and remove methods that do not exist in one of the sdk versions
  methods = methods.select do |i|
    if i.attribute('api_removed') and i.attribute('api_removed').to_i <= target_api
      puts "Can't create #{i.method_signature} -- removed in #{i.attribute('api_removed')}"
      false
    else
      true
    end
  end

  abort = false
  new_methods = methods
  unless force == 'include'
    # Inform and remove methods changed inside the scope of the sdk versions
    new_methods = methods.select do |i|
      if i.attribute('api_added') and i.attribute('api_added').to_i > min_api and force == 'exclude'
        false
      elsif i.attribute('api_added') and i.attribute('api_added').to_i > min_api
        puts "Can't create #{i.method_signature} -- added in #{i.attribute('api_added')} -- use method_exclude or force exclude"
        abort = true
        false
      elsif i.attribute('deprecated') and i.attribute('deprecated').to_i <= target_api and force == 'exclude'
        false
      elsif i.attribute('deprecated') and i.attribute('deprecated').to_i <= target_api
        puts "Can't create #{i.method_signature} -- deprecated in #{i.attribute('deprecated')} -- use method_exclude or force exclude"
        abort = true
        false
      else
        true
      end
    end

    abort('Aborting!') if abort
  end

  new_methods
end

#generate_core_classes(params) ⇒ Object

generate_core_classe: generates RubotoActivity, RubotoService, etc. based

on the API specifications.

132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/ruboto/util/build.rb', line 132

def generate_core_classes(params)
  hash = {:package => 'org.ruboto'}
  %w(method_base method_include implements force).inject(hash) { |h, i| h[i.to_sym] = params[i.to_sym]; h }
  hash[:method_exclude] = params[:method_exclude]

  %w(android.app.Activity android.app.Service android.content.BroadcastReceiver).each do |i|
    name = i.split('.')[-1]
    if params[:class] == name or params[:class] == 'all'
      generate_subclass_or_interface(hash.merge({:template => "Ruboto#{name}", :class => i, :name => "Ruboto#{name}"}))
    end
  end

  # Activities that can be created, but only directly  (i.e., not included in all)
  %w(android.preference.PreferenceActivity android.app.TabActivity).each do |i|
    name = i.split('.')[-1]
    if params[:class] == name
      generate_subclass_or_interface(hash.merge({:template => 'RubotoActivity', :class => i, :name => "Ruboto#{name}"}))
    end
  end
end

#generate_inheriting_file(klass, name, package = verify_package, script_name = "#{underscore(name)}.rb") ⇒ Object

generate_inheriting_file:

Builds a script based subclass of Activity, Service, or BroadcastReceiver

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/ruboto/util/build.rb', line 158

def generate_inheriting_file(klass, name, package = verify_package, script_name = "#{underscore(name)}.rb")
  dest = '.'
  file = File.expand_path File.join(dest, "src/#{package.gsub('.', '/')}", "#{name}.java")
  text = File.read(File.join(Ruboto::ASSETS, "src/Inheriting#{klass}.java"))
  file_existed = File.exists?(file)
  File.open(file, 'w') do |f|
    f << text.gsub('THE_PACKAGE', package).gsub("Sample#{klass}", name).gsub("Inheriting#{klass}", name).gsub("sample_#{underscore(klass)}.rb", script_name)
  end
  puts "#{file_existed ? 'Updated' : 'Added'} file #{file}."

  script_file = File.expand_path("#{SCRIPTS_DIR}/#{script_name}", dest)
  unless File.exists? script_file
    sample_source = File.read(File.join(Ruboto::ASSETS, "samples/sample_#{underscore klass}.rb"))
    sample_source.gsub!('THE_PACKAGE', package)
    sample_source.gsub!("Sample#{klass}", name)
    sample_source.gsub!('start.rb', script_name)
    FileUtils.mkdir_p File.join(dest, SCRIPTS_DIR)
    File.open script_file, 'a' do |f|
      f << sample_source
    end
    puts "Added file #{script_file}."
  end

  test_file = File.expand_path("test/src/#{script_name.chomp('.rb')}_test.rb", dest)
  unless File.exists? test_file
    sample_test_source = File.read(File.join(Ruboto::ASSETS, "samples/sample_#{underscore klass}_test.rb"))
    sample_test_source.gsub!('THE_PACKAGE', package)
    sample_test_source.gsub!("Sample#{klass}", name)
    sample_test_source.gsub!('SampleActivity', verify_activity)
    File.open test_file, 'a' do |f|
      f << sample_test_source
    end
    puts "Added file #{test_file}."
  end
end

#generate_subclass_or_interface(params) ⇒ Object

generate_subclass_or_interface: Creates a subclass or interface based on the specifications.


100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/ruboto/util/build.rb', line 100

def generate_subclass_or_interface(params)
  defaults = {:template => 'InheritingClass', :method_base => 'all', :method_include => '', :method_exclude => '', :force => nil, :implements => ''}
  params = defaults.merge(params)
  params[:package] ||= verify_package

  class_desc = get_class_or_interface(params[:class] || params[:interface], params[:force])

  print "Generating methods for #{params[:name]}..."
  methods = class_desc.all_methods(params[:method_base], params[:method_include], params[:method_exclude], params[:implements])
  methods = check_methods(methods, params[:force])
  puts "Done. Methods created: #{methods.count}"

  params[:implements] = params[:implements].split(',').push('org.ruboto.RubotoComponent').join(',')

  action = class_desc.name == 'class' ? 'extends' : 'implements'
  build_file params[:template], params[:package], params[:name], {
      'THE_METHOD_BASE' => params[:method_base].to_s,
      'THE_PACKAGE' => params[:package],
      'THE_ACTION' => action,
      'THE_ANDROID_CLASS' => (params[:class] || params[:interface]) +
          (params[:implements] == '' ? '' : ((action != 'implements' ? ' implements ' : ', ') + params[:implements].split(',').join(', '))),
      'THE_RUBOTO_CLASS' => params[:name],
      'THE_CONSTRUCTORS' => class_desc.name == 'class' ?
          class_desc.get_elements('constructor').map { |i| i.constructor_definition(params[:name]) }.join("\n\n") : '',
      'THE_METHODS' => methods_header + methods.map { |i| i.method_definition(params[:name]) }.join("\n\n")
  }
end

#get_class_or_interface(klass, force = nil) ⇒ Object

get_class_or_interface: Opens the xml file and locates the specified class.

Aborts if the class is not found or if it is not available for
all api levels

32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/ruboto/util/build.rb', line 32

def get_class_or_interface(klass, force=nil)
  element = verify_api.find_class_or_interface(klass, 'either')

  abort "ERROR: #{klass} not found" unless element

  unless force == 'include'
    abort "#{klass} not available in minSdkVersion, added in #{element.attribute('api_added')}; use '--force include' to create it" if element.attribute('api_added') and element.attribute('api_added').to_i > verify_min_sdk.to_i
    abort "#{klass} deprecated for targetSdkVersion, deprecated in #{element.attribute('deprecated')}; use '--force include' to create it" if element.attribute('deprecated') and element.attribute('deprecated').to_i <= verify_target_sdk.to_i
  end

  abort "#{klass} removed for targetSdkVersion, removed in #{element.attribute('api_removed')}" if element.attribute('api_removed') and element.attribute('api_removed').to_i <= verify_target_sdk.to_i

  element
end

#methods_headerObject


194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/ruboto/util/build.rb', line 194

def methods_header
  <<EOF
    private final ScriptInfo scriptInfo = new ScriptInfo();
    public ScriptInfo getScriptInfo() {
  return scriptInfo;
    }

    /****************************************************************************************
     *
     *  Generated Methods
     */

EOF
end