arc_weld 0.2.5
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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +3 -0
- data/Guardfile +58 -0
- data/LICENSE.txt +674 -0
- data/README.md +73 -0
- data/Rakefile +6 -0
- data/arc_weld.gemspec +34 -0
- data/bin/setup +7 -0
- data/bin/weld +8 -0
- data/lib/arc_weld/archive.rb +87 -0
- data/lib/arc_weld/cli/project.rb +116 -0
- data/lib/arc_weld/cli/readers/relation_csv.rb +41 -0
- data/lib/arc_weld/cli/readers/resource_csv.rb +64 -0
- data/lib/arc_weld/cli.rb +45 -0
- data/lib/arc_weld/helpers.rb +12 -0
- data/lib/arc_weld/reference.rb +51 -0
- data/lib/arc_weld/relationship.rb +96 -0
- data/lib/arc_weld/relationships/customer_of.rb +28 -0
- data/lib/arc_weld/relationships/has_alternate_interface.rb +27 -0
- data/lib/arc_weld/relationships/has_child.rb +42 -0
- data/lib/arc_weld/relationships/has_customer.rb +28 -0
- data/lib/arc_weld/relationships/has_location.rb +16 -0
- data/lib/arc_weld/relationships/in_category.rb +26 -0
- data/lib/arc_weld/relationships/in_network.rb +26 -0
- data/lib/arc_weld/relationships/in_zone.rb +41 -0
- data/lib/arc_weld/relationships/location_of.rb +28 -0
- data/lib/arc_weld/resource.rb +149 -0
- data/lib/arc_weld/resource_definitions.rb +7 -0
- data/lib/arc_weld/resources/asset.rb +33 -0
- data/lib/arc_weld/resources/asset_category.rb +40 -0
- data/lib/arc_weld/resources/customer.rb +16 -0
- data/lib/arc_weld/resources/group.rb +29 -0
- data/lib/arc_weld/resources/location.rb +18 -0
- data/lib/arc_weld/resources/network.rb +14 -0
- data/lib/arc_weld/resources/zone.rb +65 -0
- data/lib/arc_weld/templates/project-csv/.gitignore.tt +2 -0
- data/lib/arc_weld/templates/project-csv/Gemfile.tt +3 -0
- data/lib/arc_weld/templates/project-csv/Thorfile.tt +9 -0
- data/lib/arc_weld/templates/project-csv/in/assets.csv.tt +2 -0
- data/lib/arc_weld/templates/project-csv/in/categories.csv.tt +3 -0
- data/lib/arc_weld/templates/project-csv/in/customer_groups.csv.tt +3 -0
- data/lib/arc_weld/templates/project-csv/in/customers.csv.tt +3 -0
- data/lib/arc_weld/templates/project-csv/in/group_categories.csv.tt +3 -0
- data/lib/arc_weld/templates/project-csv/in/locations.csv.tt +6 -0
- data/lib/arc_weld/templates/project-csv/in/networks.csv.tt +3 -0
- data/lib/arc_weld/templates/project-csv/in/zone_locations.csv.tt +2 -0
- data/lib/arc_weld/templates/project-csv/in/zones.csv.tt +2 -0
- data/lib/arc_weld/templates/project-csv/lib/thor/README.txt.tt +2 -0
- data/lib/arc_weld/templates/project-csv/lib/thor/sample.thor.tt +7 -0
- data/lib/arc_weld/templates/project-csv/out/README-archive.txt.tt +5 -0
- data/lib/arc_weld/templates/project-csv/weld.json.tt +39 -0
- data/lib/arc_weld/version.rb +3 -0
- data/lib/arc_weld.rb +19 -0
- metadata +269 -0
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# ArcWeld
|
2
|
+
|
3
|
+
[](https://travis-ci.org/ryanbreed/arc_weld)
|
4
|
+
|
5
|
+
Toolkit for generating ArcSight resources. Useful for fine-grained control
|
6
|
+
over the asset model. Currently supports generating the following resource
|
7
|
+
types:
|
8
|
+
|
9
|
+
- Asset
|
10
|
+
- AssetCategory
|
11
|
+
- Customer
|
12
|
+
- Location
|
13
|
+
- Network
|
14
|
+
- Zone
|
15
|
+
- Groups of the above resources
|
16
|
+
|
17
|
+
Basic support classes included for building resource XML archives and reading
|
18
|
+
resources from CSV files. You can also model supported relationships between
|
19
|
+
the resources using the relationship extension modules. This lets you do things
|
20
|
+
like add a location to zones, add a network to a customer, categorize resources,
|
21
|
+
etc.
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
## **WARNING**
|
26
|
+
|
27
|
+
You will completely trash your ESM if you do not understand *exactly* what
|
28
|
+
you are getting into with the archive tool. There's many reasons why not much
|
29
|
+
documentation exists on the subject. `$MANAGER_HOME/bin/arcsight archive -h`
|
30
|
+
to get started on that journey. Also, there is no guarantee that HP will
|
31
|
+
even continue to expose the archive tool interface. It could be deprecated
|
32
|
+
at any time in any release with no notice.
|
33
|
+
|
34
|
+
## Installation
|
35
|
+
|
36
|
+
Add this line to your application's Gemfile:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
gem 'arc_weld'
|
40
|
+
```
|
41
|
+
|
42
|
+
And then execute:
|
43
|
+
|
44
|
+
$ bundle
|
45
|
+
|
46
|
+
Or install it yourself as:
|
47
|
+
|
48
|
+
$ gem install arc_weld
|
49
|
+
|
50
|
+
## Usage
|
51
|
+
|
52
|
+
So far, the spec files contain the most complete description of how to use the
|
53
|
+
resource classes and relationship modules. There is a basic cli tool for
|
54
|
+
creating a csv-based model project and using that to generate the model xml.
|
55
|
+
Bear in mind that you can always break up a modeling effort into multiple smaller
|
56
|
+
projects and merge them in the target ESM if that makes more sense.
|
57
|
+
|
58
|
+
`ArcWeld::Resource` and `ArcWeld::Relationship` define the core DSL for describing
|
59
|
+
resources and relationships. The code for the resources and relationships themselves
|
60
|
+
are defined under `lib/arc_weld/resources` and `lib/arc_weld/relationships`.
|
61
|
+
|
62
|
+
Be advised - this is also an experiment for me, so some things could be better
|
63
|
+
organized. This will happen before I cut a 1.0.0.
|
64
|
+
|
65
|
+
## Licensed under GPLv3
|
66
|
+
|
67
|
+
## Development
|
68
|
+
|
69
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
70
|
+
|
71
|
+
## Contributing
|
72
|
+
|
73
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/ryanbreed/arc_weld.
|
data/Rakefile
ADDED
data/arc_weld.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'arc_weld/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'arc_weld'
|
8
|
+
spec.version = ArcWeld::VERSION
|
9
|
+
spec.authors = ['Ryan Breed']
|
10
|
+
spec.email = ['opensource@breed.org']
|
11
|
+
|
12
|
+
spec.summary = 'Toolkit for building ArcSight resources'
|
13
|
+
spec.description = 'Toolkit for building ArcSight resources'
|
14
|
+
spec.homepage = 'https://github.com/ryanbreed/arc_weld'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = 'bin'
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'gyoku'
|
22
|
+
spec.add_dependency 'nokogiri'
|
23
|
+
spec.add_dependency 'thor'
|
24
|
+
|
25
|
+
spec.add_development_dependency 'pry'
|
26
|
+
spec.add_development_dependency 'pry-doc'
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
28
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
+
spec.add_development_dependency 'rspec'
|
30
|
+
spec.add_development_dependency 'guard'
|
31
|
+
spec.add_development_dependency 'guard-rspec'
|
32
|
+
spec.add_development_dependency 'guard-bundler'
|
33
|
+
spec.add_development_dependency 'simplecov'
|
34
|
+
end
|
data/bin/setup
ADDED
data/bin/weld
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$LOAD_PATH.push(File.join(File.expand_path(File.dirname(__FILE__)), '..','lib'))
|
3
|
+
require 'arc_weld'
|
4
|
+
if Dir.exist?(local_lib=File.join(Dir.pwd,'lib'))
|
5
|
+
Dir[File.join(local_lib,'*.rb')]. each {|local_lib| require local_lib }
|
6
|
+
end
|
7
|
+
|
8
|
+
ArcWeld::WeldCli.start(ARGV)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module ArcWeld
|
2
|
+
class Archive
|
3
|
+
attr_accessor :resources, :createTime, :dtd_location
|
4
|
+
|
5
|
+
BUILD_VERSION = '6.5.1.1952.1'
|
6
|
+
BUILD_TIME = '3-6-2015_17:2:26'
|
7
|
+
TIME_FORMAT = '%m-%d-%Y_%H:%M:%S'
|
8
|
+
|
9
|
+
PARSE_DEFAULT = Nokogiri::XML::ParseOptions::DEFAULT_XML
|
10
|
+
PARSE_VALIDATE = Nokogiri::XML::ParseOptions::DEFAULT_XML | Nokogiri::XML::ParseOptions::DTDLOAD
|
11
|
+
|
12
|
+
ARCHIVE_DTD = "../../schema/xml/archive/arcsight-archive.dtd"
|
13
|
+
|
14
|
+
def initialize(*args)
|
15
|
+
Hash[*args].each {|k,v| self.send(format('%s=',k),v)}
|
16
|
+
@resources ||= []
|
17
|
+
@createTime ||= Time.new
|
18
|
+
@dtd_location ||= ARCHIVE_DTD
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def include_list
|
23
|
+
resources.map {|g| g.ref.render }.join('')
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_item(item)
|
27
|
+
resources.push(item) unless resources.include?(item)
|
28
|
+
end
|
29
|
+
|
30
|
+
def add(*items)
|
31
|
+
items.each { |item| add_item(item) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def dtd(location=ARCHIVE_DTD)
|
35
|
+
format('<!DOCTYPE archive SYSTEM "%s">', dtd_location)
|
36
|
+
end
|
37
|
+
|
38
|
+
def archive_creation_parameters
|
39
|
+
acp = {
|
40
|
+
ArchiveCreationParameters: {
|
41
|
+
:action => 'insert',
|
42
|
+
'excludeReferenceIDs/' => '',
|
43
|
+
:format => 'default',
|
44
|
+
'formatRoot/' => ''
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
if resources.empty?
|
49
|
+
acp[:ArchiveCreationParameters]['include/'] = ''
|
50
|
+
else
|
51
|
+
acp[:ArchiveCreationParameters][:include] = { :list! => include_list }
|
52
|
+
end
|
53
|
+
|
54
|
+
Gyoku.xml(acp, {key_converter: :none})
|
55
|
+
end
|
56
|
+
|
57
|
+
def create_time
|
58
|
+
@createTime.strftime(TIME_FORMAT)
|
59
|
+
end
|
60
|
+
|
61
|
+
def resource_content
|
62
|
+
resources.map {|res| res.render }.join('')
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_h
|
66
|
+
archive_h = {
|
67
|
+
:archive! => archive_creation_parameters + resource_content,
|
68
|
+
:attributes! => {
|
69
|
+
:archive! => {
|
70
|
+
:buildVersion => BUILD_VERSION,
|
71
|
+
:buildTime => BUILD_TIME,
|
72
|
+
:createTime => create_time
|
73
|
+
}
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def render
|
79
|
+
Gyoku.xml(to_h, {key_converter: :none} )
|
80
|
+
end
|
81
|
+
|
82
|
+
def xml(options=PARSE_DEFAULT)
|
83
|
+
Nokogiri.XML(dtd + render, nil, 'UTF-8', options)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module ArcWeld
|
2
|
+
module Cli
|
3
|
+
class Project
|
4
|
+
include ArcWeld::Helpers
|
5
|
+
attr_accessor :name, :input_dir, :output_dir, :resource_driver,
|
6
|
+
:resource_root, :resource_inputs, :relationships, :base_model
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
config.each {|k,v| self.send(format('%s=',k),v)}
|
10
|
+
self
|
11
|
+
end
|
12
|
+
|
13
|
+
def resource_class_for(resource_type)
|
14
|
+
ArcWeld.const_get(constantize(resource_type))
|
15
|
+
end
|
16
|
+
|
17
|
+
def resource_input_path(resource_type)
|
18
|
+
File.join(self.input_dir, resource_inputs.fetch(resource_type))
|
19
|
+
end
|
20
|
+
|
21
|
+
def resource_reader(resource_type)
|
22
|
+
klass = ArcWeld::Cli::ResourceReaders.const_get(constantize(resource_driver))
|
23
|
+
klass.new( path: resource_input_path(resource_type),
|
24
|
+
target_class: resource_class_for(resource_type) )
|
25
|
+
end
|
26
|
+
|
27
|
+
def reader
|
28
|
+
@readers ||= Hash[
|
29
|
+
resource_inputs.keys.map { |type| [type, resource_reader(type)]}
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
def resources
|
34
|
+
@resources ||= Hash.new {|h,k| h[k]=Array.new }
|
35
|
+
end
|
36
|
+
|
37
|
+
def archive_resources(resource_type)
|
38
|
+
archive.resources.select {|r| r.resource_type == constantize(resource_type)}
|
39
|
+
end
|
40
|
+
|
41
|
+
def archive
|
42
|
+
@archive ||= Archive.new
|
43
|
+
end
|
44
|
+
|
45
|
+
def load_resources
|
46
|
+
reader.each do |type, type_reader|
|
47
|
+
res=type_reader.to_a
|
48
|
+
resources[type].push(*res)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def resource_group(type)
|
53
|
+
klass = ArcWeld.const_get(constantize(type))
|
54
|
+
group_name = resource_root[type]
|
55
|
+
ArcWeld::Group.new(
|
56
|
+
name: group_name,
|
57
|
+
externalID: format('weld_%s_root', type),
|
58
|
+
description: format('ArcWeld root %s group',
|
59
|
+
constantize(type)),
|
60
|
+
containedResourceType: klass.class_id,
|
61
|
+
parent_ref: klass.toplevel
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
def resource_roots
|
66
|
+
@roots ||= Hash[
|
67
|
+
resource_root.map do |type, group_name|
|
68
|
+
grp = resource_group(type)
|
69
|
+
resources['group'].push(grp)
|
70
|
+
[type, grp ]
|
71
|
+
end
|
72
|
+
]
|
73
|
+
end
|
74
|
+
|
75
|
+
def zone_assets
|
76
|
+
resources['asset'].each do |asset|
|
77
|
+
asset.auto_zone(*resources['zone'])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def assign_model_relations
|
82
|
+
relationships.each do |rel|
|
83
|
+
klass = ArcWeld::Cli::RelationReaders.const_get(constantize(rel['driver']))
|
84
|
+
rel_reader = klass.new(
|
85
|
+
path: File.join(input_dir,rel['file']),
|
86
|
+
relationship_type: rel['type'] )
|
87
|
+
sources = resources[rel_reader.src_type]
|
88
|
+
dests = resources[rel_reader.dst_type]
|
89
|
+
rel_reader.relate(sources,dests)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def assign_resource_groups
|
94
|
+
resource_roots['zone'].add_children(*resources['zone'])
|
95
|
+
|
96
|
+
zone_assets
|
97
|
+
|
98
|
+
unzoned = resources['asset'].select {|a| a.in_zone.nil?}
|
99
|
+
resource_roots['asset'].add_children(*unzoned)
|
100
|
+
|
101
|
+
%w{ network customer location asset_category }.each do |type|
|
102
|
+
resource_roots[type].add_children(*resources[type])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def generate_archive
|
107
|
+
resource_roots
|
108
|
+
load_resources
|
109
|
+
assign_resource_groups
|
110
|
+
assign_model_relations
|
111
|
+
archive.add(*resources.values.flatten)
|
112
|
+
archive
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module ArcWeld
|
2
|
+
module Cli
|
3
|
+
module RelationReaders
|
4
|
+
class Csv
|
5
|
+
include ArcWeld::Helpers
|
6
|
+
attr_accessor :path, :relationship_type,
|
7
|
+
:src_select, :dst_select,
|
8
|
+
:src_class, :dst_class
|
9
|
+
|
10
|
+
attr_reader :csv, :keys, :src_type, :dst_type
|
11
|
+
|
12
|
+
def initialize(*args)
|
13
|
+
Hash[*args].each {|k,v| self.send(format('%s=',k),v)}
|
14
|
+
@csv = CSV.open(path)
|
15
|
+
@keys = csv.readline
|
16
|
+
@src_type, @src_select, @dst_type, @dst_select = keys.flat_map do |k|
|
17
|
+
k.split(':')
|
18
|
+
end
|
19
|
+
@src_class=ArcWeld.const_get(constantize(src_type))
|
20
|
+
@dst_class=ArcWeld.const_get(constantize(dst_type))
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def relate(sources,destinations)
|
25
|
+
csv.each do |selected_src, selected_dst|
|
26
|
+
src_instance=sources.find {|s| s.send(src_select)==selected_src}
|
27
|
+
dst_instance=destinations.find {|s| s.send(dst_select)==selected_dst}
|
28
|
+
if (src_instance.nil? || dst_instance.nil?)
|
29
|
+
STDERR.puts format('could not %s %s/%s',
|
30
|
+
relationship_type,
|
31
|
+
selected_src,
|
32
|
+
selected_dst)
|
33
|
+
else
|
34
|
+
src_instance.send(relationship_type,dst_instance)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module ArcWeld
|
4
|
+
module Cli
|
5
|
+
module ResourceReaders
|
6
|
+
class Csv
|
7
|
+
attr_accessor :path, :target_class, :key_proc
|
8
|
+
attr_reader :keys, :csv
|
9
|
+
DEFAULT_OPTIONS = {skip_lines: %r{\A[#;]}}
|
10
|
+
|
11
|
+
def initialize(path: nil, target_class: nil, options: DEFAULT_OPTIONS)
|
12
|
+
@path, @target_class = path, target_class
|
13
|
+
@csv = CSV.open(path, 'r', options)
|
14
|
+
@key_proc ||= {}
|
15
|
+
@keys = csv.readline.map { |k| k.to_sym }
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_keys
|
19
|
+
keys - processed_keys
|
20
|
+
end
|
21
|
+
|
22
|
+
def processed_keys
|
23
|
+
key_proc.keys
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse(array)
|
27
|
+
row_hash = Hash[keys.zip(array)]
|
28
|
+
instance_hash = row_hash.select {|k,v| read_keys.include?(k)}
|
29
|
+
new_instance = target_class.new(instance_hash)
|
30
|
+
|
31
|
+
if processed_keys.empty?
|
32
|
+
new_instance
|
33
|
+
else
|
34
|
+
processed_hash = row_hash.select {|k,v| read_keys.include?(k)==false }
|
35
|
+
processed_hash.each do |processed_key, processed_value|
|
36
|
+
key_proc.fetch(processed_key).call(processed_key,processed_value,new_instance)
|
37
|
+
end
|
38
|
+
new_instance
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def not_at_start_record?
|
43
|
+
(csv.lineno!=1)
|
44
|
+
end
|
45
|
+
|
46
|
+
def each(rewind: not_at_start_record?)
|
47
|
+
reset_csv if rewind
|
48
|
+
csv.each {|arr| yield parse(arr) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_a(rewind: not_at_start_record?)
|
52
|
+
reset_csv if rewind
|
53
|
+
csv.readlines.map {|arr| parse(arr)}
|
54
|
+
end
|
55
|
+
|
56
|
+
def reset_csv
|
57
|
+
csv.rewind
|
58
|
+
*trash = csv.readline
|
59
|
+
csv.lineno
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/arc_weld/cli.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'arc_weld'
|
2
|
+
require 'arc_weld/cli/project'
|
3
|
+
require 'arc_weld/cli/readers/relation_csv'
|
4
|
+
require 'arc_weld/cli/readers/resource_csv'
|
5
|
+
require 'openssl'
|
6
|
+
require 'json'
|
7
|
+
module ArcWeld
|
8
|
+
class WeldCli < Thor
|
9
|
+
|
10
|
+
include Thor::Actions
|
11
|
+
def self.source_root
|
12
|
+
@source_root ||= File.join( File.dirname( File.expand_path(__FILE__) ),
|
13
|
+
'templates')
|
14
|
+
end
|
15
|
+
|
16
|
+
class_option :config,
|
17
|
+
type: :string,
|
18
|
+
default: 'weld.json',
|
19
|
+
desc: 'config file'
|
20
|
+
|
21
|
+
desc 'new PROJECT_NAME', 'generate new project'
|
22
|
+
option :dir,
|
23
|
+
type: :string,
|
24
|
+
default: Dir.pwd,
|
25
|
+
desc: 'create project directory here'
|
26
|
+
option :driver,
|
27
|
+
type: :string,
|
28
|
+
default: 'csv',
|
29
|
+
desc: 'driver for reading resources and relations'
|
30
|
+
def new(name)
|
31
|
+
self.destination_root = options[:dir]
|
32
|
+
@config = options.merge(name: name)
|
33
|
+
directory(format('project-%s',options[:driver]),name)
|
34
|
+
end
|
35
|
+
|
36
|
+
desc 'generate FILENAME', 'render entire model in FILENAME'
|
37
|
+
def generate(filename='model.xml')
|
38
|
+
config = JSON.parse(File.read(options[:config]))
|
39
|
+
project = ArcWeld::Cli::Project.new(config)
|
40
|
+
outfile = File.join(project.output_dir, filename)
|
41
|
+
archive = project.generate_archive
|
42
|
+
File.open(outfile,'w') {|f| f.puts archive.xml.to_s }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module ArcWeld
|
2
|
+
module Helpers
|
3
|
+
def constantize(literal)
|
4
|
+
(literal.to_s.split(%r{[ _]}).map &:capitalize).join('')
|
5
|
+
end
|
6
|
+
|
7
|
+
def uri_join(*parts)
|
8
|
+
pieces=parts.flat_map {|p| p.to_s.gsub(%r{\A/},'').gsub(%r{/\z},'')}
|
9
|
+
format('/%s', pieces.join('/'))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ArcWeld
|
2
|
+
class Reference
|
3
|
+
attr_accessor :type, :uri, :id, :externalID
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
Hash[*args].each {|k,v| self.send(format('%s=',k),v)}
|
7
|
+
@type ||= 'Group'
|
8
|
+
end
|
9
|
+
|
10
|
+
def ref
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other)
|
15
|
+
[:type, :uri, :id, :externalID].all? do |attr|
|
16
|
+
self.send(attr) == other.send(attr)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def identity_hash
|
21
|
+
if identity=={}
|
22
|
+
{}
|
23
|
+
else
|
24
|
+
Hash[identity.keys.map {|k| format('@%s',k.to_s)}.zip(identity.values)]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def identity
|
29
|
+
if id!=nil
|
30
|
+
{:id => id}
|
31
|
+
elsif externalID!=nil
|
32
|
+
{:externalID => externalID}
|
33
|
+
else
|
34
|
+
{}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_h
|
39
|
+
{
|
40
|
+
'ref/' => {
|
41
|
+
:@type => type,
|
42
|
+
:@uri => uri
|
43
|
+
}.merge(identity_hash)
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def render
|
48
|
+
Gyoku.xml(to_h, key_converter: :none)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'arc_weld/relationships/customer_of'
|
2
|
+
require 'arc_weld/relationships/location_of'
|
3
|
+
require 'arc_weld/relationships/has_alternate_interface'
|
4
|
+
require 'arc_weld/relationships/has_child'
|
5
|
+
require 'arc_weld/relationships/has_customer'
|
6
|
+
require 'arc_weld/relationships/has_location'
|
7
|
+
require 'arc_weld/relationships/in_category'
|
8
|
+
require 'arc_weld/relationships/in_network'
|
9
|
+
require 'arc_weld/relationships/in_zone'
|
10
|
+
|
11
|
+
module ArcWeld
|
12
|
+
module Relationship
|
13
|
+
|
14
|
+
def self.included(klass)
|
15
|
+
klass.class_eval '@@RELATIONSHIPS = []'
|
16
|
+
klass.class_eval do
|
17
|
+
extend ClassMethods
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def relationship_types
|
23
|
+
self.class.class_variable_get :@@RELATIONSHIPS
|
24
|
+
end
|
25
|
+
|
26
|
+
def relationship_hash
|
27
|
+
relationship_types.reduce({}) do |memo, key|
|
28
|
+
meth = format('%s_relationship',key)
|
29
|
+
if self.send(meth).nil?
|
30
|
+
memo
|
31
|
+
else
|
32
|
+
memo.merge(self.send(meth))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
def has_relationship(*args)
|
39
|
+
#puts format('defining relationship on %s', self.name)
|
40
|
+
options=case args[-1]
|
41
|
+
when Hash
|
42
|
+
args.pop
|
43
|
+
else
|
44
|
+
Hash.new(false)
|
45
|
+
end
|
46
|
+
|
47
|
+
args.each do |sym|
|
48
|
+
register_relationship(sym,options[:multiple])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def class_relationship_types
|
53
|
+
class_variable_get :@@RELATIONSHIPS
|
54
|
+
end
|
55
|
+
|
56
|
+
def register_relationship(name, multiple=false)
|
57
|
+
unless class_relationship_types.include?(name)
|
58
|
+
class_relationship_types << name
|
59
|
+
|
60
|
+
if ArcWeld::Relationships.const_defined? constantize(name)
|
61
|
+
self.class_eval "include ArcWeld::Relationships::#{constantize(name)}"
|
62
|
+
end
|
63
|
+
# TODO: this is a horrible mess
|
64
|
+
unless self.method_defined? name
|
65
|
+
if multiple
|
66
|
+
self.class_eval do
|
67
|
+
define_method("#{name}") do
|
68
|
+
val = self.instance_variable_get("@#{name}")
|
69
|
+
if val.nil?
|
70
|
+
self.instance_variable_set("@#{name}",[])
|
71
|
+
end
|
72
|
+
self.instance_variable_get("@#{name}")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
else
|
76
|
+
self.class_eval do
|
77
|
+
define_method("#{name}") do
|
78
|
+
self.instance_variable_get("@#{name}")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
unless self.method_defined? "#{name}="
|
84
|
+
self.class_eval do
|
85
|
+
define_method("#{name}=") do |val|
|
86
|
+
self.instance_variable_set("@#{name}",val)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module ArcWeld
|
2
|
+
module Relationships
|
3
|
+
module CustomerOf
|
4
|
+
def add_customer_resource(res)
|
5
|
+
unless customer_of.include?(res)
|
6
|
+
customer_of.push(res)
|
7
|
+
res.add_customer(self)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_customer_resources(*resources)
|
12
|
+
resources.each { |res| add_customer_resource(res) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def related_customer_of_references
|
16
|
+
(customer_of.map { |resource| resource.ref.render }).join
|
17
|
+
end
|
18
|
+
|
19
|
+
def customer_of_relationship
|
20
|
+
unless customer_of.empty?
|
21
|
+
{ 'customerOf' => {
|
22
|
+
'list!' => related_customer_of_references
|
23
|
+
}}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|