mpxj 5.1.9 → 5.1.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 341098bd06b4186e6228fcfc40c4d1a36ac2d90e
4
- data.tar.gz: 8feda84984b5742bc2a0b6418ea16dfcccf097bf
3
+ metadata.gz: 14e3c6791d8518f3cac4f787d9d4cc94b6dd76da
4
+ data.tar.gz: 3f6e8363e3a72ad46cb10739e21a315296480ae6
5
5
  SHA512:
6
- metadata.gz: 3f2fb3a5184d5996f87c40545b14e7d4afd37e42c8644e26c8624a8d000ea32633f0b6b7255d0ca106bac2658df1c151860b136405d9ee87cd563a98fae9ef6c
7
- data.tar.gz: 1ce8e7b048a800b535ea4bb789f42e0ba43d000386d14f2172f25b6680eb777234a7c3955b26ec7fce3e232c2afc06a096994d663cd960078250781ca64ecdfe
6
+ metadata.gz: 52a0b516a7604f65574f1dccff38de2e1ff8767e67538e2159098d8d1743a4def4bc4b85312c28141a7cd11bb29094d87f929c96bf1901d598fe93caf2d27a1d
7
+ data.tar.gz: acf7cfa6573b31342e3a95c786b163282e4ab6cea1123459201224750a0f409677187aaba75c844232ab90671bbcb40f769bda2702ad394f232b966ee3d07910
data/README.md CHANGED
@@ -3,7 +3,10 @@
3
3
  This gem allows a Ruby developer to work with a read-only view of project plans saved by a number of popular project planning applications.
4
4
  The work required to read data from these files is actually carried out by a [Java library](http://mpxj.sf.net), hence you will need Java installed
5
5
  and available on your path in order to work with this gem. Once the project data has been read from a file, a set of Ruby objects provides access to the
6
- structure of the project plan and its attributes.
6
+ structure of the project plan and its attributes.
7
+
8
+ This gem only came about through the interest and support of Procore, who would love to [hear from you](https://www.procore.com/jobs/)
9
+ if you're excited about working with Ruby and Rails.
7
10
 
8
11
  ## Installation
9
12
 
@@ -1,89 +1,89 @@
1
- require 'duration'
2
- require 'time'
3
-
4
- module MPXJ
5
- # Base class from which all project entities are derived
6
- class Container
7
- attr_reader :parent_project
8
- def initialize(parent_project, attribute_types, attribute_values)
9
- @parent_project = parent_project
10
- @attribute_types = attribute_types
11
- @attribute_values = attribute_values
12
- end
13
-
14
- def method_missing(name, *args, &block)
15
- # We can probably do this more efficiently with dynamic methods... but let's get some feedback first!
16
- attribute_name = name.to_s
17
- attribute_type = @attribute_types[attribute_name]
18
- attribute_value = @attribute_values[attribute_name]
19
-
20
- if attribute_type.nil? && attribute_value.nil?
21
- super
22
- else
23
- if attribute_type.nil?
24
- attribute_type = 1
25
- end
26
- get_attribute_value(attribute_type, attribute_value)
27
- end
28
- end
29
-
30
- protected
31
-
32
- attr_reader :attribute_values
33
-
34
- private
35
-
36
- def get_attribute_value(attribute_type, attribute_value)
37
- case attribute_type.to_i
38
- when 12, 17, 19
39
- get_integer_value(attribute_value)
40
- when 8, 3, 5, 7
41
- get_float_value(attribute_value)
42
- when 2
43
- get_date_value(attribute_value)
44
- when 6, 16
45
- get_duration_value(attribute_value)
46
- when 4
47
- get_boolean_value(attribute_value)
48
- else
49
- attribute_value
50
- end
51
- end
52
-
53
- def get_duration_value(attribute_value)
54
- if attribute_value.nil?
55
- Duration.new(0)
56
- else
57
- Duration.new(attribute_value.to_i)
58
- end
59
- end
60
-
61
- def get_date_value(attribute_value)
62
- if attribute_value.nil?
63
- nil
64
- else
65
- @parent_project.zone.parse(attribute_value)
66
- end
67
- end
68
-
69
- def get_float_value(attribute_value)
70
- if attribute_value.nil?
71
- 0.0
72
- else
73
- attribute_value.to_f
74
- end
75
- end
76
-
77
- def get_integer_value(attribute_value)
78
- if attribute_value.nil?
79
- 0
80
- else
81
- attribute_value.to_i
82
- end
83
- end
84
-
85
- def get_boolean_value(attribute_value)
86
- attribute_value == true
87
- end
88
- end
89
- end
1
+ require 'duration'
2
+ require 'time'
3
+
4
+ module MPXJ
5
+ # Base class from which all project entities are derived
6
+ class Container
7
+ attr_reader :parent_project
8
+ def initialize(parent_project, attribute_types, attribute_values)
9
+ @parent_project = parent_project
10
+ @attribute_types = attribute_types
11
+ @attribute_values = attribute_values
12
+ end
13
+
14
+ def method_missing(name, *args, &block)
15
+ # We can probably do this more efficiently with dynamic methods... but let's get some feedback first!
16
+ attribute_name = name.to_s
17
+ attribute_type = @attribute_types[attribute_name]
18
+ attribute_value = @attribute_values[attribute_name]
19
+
20
+ if attribute_type.nil? && attribute_value.nil?
21
+ super
22
+ else
23
+ if attribute_type.nil?
24
+ attribute_type = 1
25
+ end
26
+ get_attribute_value(attribute_type, attribute_value)
27
+ end
28
+ end
29
+
30
+ protected
31
+
32
+ attr_reader :attribute_values
33
+
34
+ private
35
+
36
+ def get_attribute_value(attribute_type, attribute_value)
37
+ case attribute_type.to_i
38
+ when 12, 17, 19
39
+ get_integer_value(attribute_value)
40
+ when 8, 3, 5, 7
41
+ get_float_value(attribute_value)
42
+ when 2
43
+ get_date_value(attribute_value)
44
+ when 6, 16
45
+ get_duration_value(attribute_value)
46
+ when 4
47
+ get_boolean_value(attribute_value)
48
+ else
49
+ attribute_value
50
+ end
51
+ end
52
+
53
+ def get_duration_value(attribute_value)
54
+ if attribute_value.nil?
55
+ Duration.new(0)
56
+ else
57
+ Duration.new(attribute_value.to_i)
58
+ end
59
+ end
60
+
61
+ def get_date_value(attribute_value)
62
+ if attribute_value.nil?
63
+ nil
64
+ else
65
+ @parent_project.zone.parse(attribute_value)
66
+ end
67
+ end
68
+
69
+ def get_float_value(attribute_value)
70
+ if attribute_value.nil?
71
+ 0.0
72
+ else
73
+ attribute_value.to_f
74
+ end
75
+ end
76
+
77
+ def get_integer_value(attribute_value)
78
+ if attribute_value.nil?
79
+ 0
80
+ else
81
+ attribute_value.to_i
82
+ end
83
+ end
84
+
85
+ def get_boolean_value(attribute_value)
86
+ attribute_value == true
87
+ end
88
+ end
89
+ end
Binary file
@@ -1,175 +1,175 @@
1
- require 'json'
2
-
3
- module MPXJ
4
- # Represents a project plan
5
- class Project
6
- attr_reader :properties
7
- attr_reader :all_resources
8
- attr_reader :all_tasks
9
- attr_reader :child_tasks
10
- attr_reader :all_assignments
11
- attr_reader :zone
12
-
13
- def initialize(file_name, zone)
14
- @resources_by_unique_id = {}
15
- @tasks_by_unique_id = {}
16
-
17
- @resources_by_id = {}
18
- @tasks_by_id = {}
19
-
20
- @all_resources = []
21
- @all_tasks = []
22
- @all_assignments = []
23
- @child_tasks = []
24
-
25
- @zone = zone
26
-
27
- @field_by_alias = {}
28
- @alias_by_field = {}
29
-
30
- file = File.read(file_name)
31
- json_data = JSON.parse(file)
32
- process_custom_fields(json_data)
33
- process_properties(json_data)
34
- process_resources(json_data)
35
- process_tasks(json_data)
36
- process_assignments(json_data)
37
- end
38
-
39
- # Retrieves the resource with the matching unique_id attribute
40
- #
41
- # @param unique_id [Integer] resource unique ID
42
- # @return [Resource] if the requested resource is found
43
- # @return [nil] if the requested resource is not found
44
- def get_resource_by_unique_id(unique_id)
45
- @resources_by_unique_id[unique_id]
46
- end
47
-
48
- # Retrieves the task with the matching unique_id attribute
49
- #
50
- # @param unique_id [Integer] task unique ID
51
- # @return [Task] if the requested task is found
52
- # @return [nil] if the requested task is not found
53
- def get_task_by_unique_id(unique_id)
54
- @tasks_by_unique_id[unique_id]
55
- end
56
-
57
- # Retrieves the resource with the matching id attribute
58
- #
59
- # @param id [Integer] resource ID
60
- # @return [Resource] if the requested resource is found
61
- # @return [nil] if the requested resource is not found
62
- def get_resource_by_id(id)
63
- @resources_by_id[id]
64
- end
65
-
66
- # Retrieves the task with the matching id attribute
67
- #
68
- # @param id [Integer] task ID
69
- # @return [Task] if the requested task is found
70
- # @return [nil] if the requested task is not found
71
- def get_task_by_id(id)
72
- @tasks_by_unique_id[id]
73
- end
74
-
75
- # For a particular entity type (task, resource, and so on), retrieve
76
- # the field which has the supplied alias. For example this allows the caller to
77
- # answer the question "which task field is using the alias `Activity ID`"
78
- #
79
- # @param field_type_class[String] field type (possible values: task, resource, assignment, constraint, project)
80
- # @param field_alias[String] the alias we want to look up
81
- # @return [String] if the alias has been found return the name of the underlying field
82
- # @return [nil] if the alias is not in use
83
- def get_field_by_alias(field_type_class, field_alias)
84
- hash = @field_by_alias[field_type_class]
85
- if hash
86
- hash[field_alias]
87
- end
88
- end
89
-
90
- # For a particular entity type (task, resource, and so on), retrieve
91
- # the alias used by the supplied field. For example this allows the caller to
92
- # answer the question "does the task field Text1 have an alias?"
93
- #
94
- # @param field_type_class[String] field type (possible values: task, resource, assignment, constraint, project)
95
- # @param field_type[String] the field type we want to look up
96
- # @return [String] if the field has an alias, return the alias
97
- # @return [nil] if the field does not have an alias
98
- def get_alias_by_field(field_type_class, field_type)
99
- hash = @alias_by_field[field_type_class]
100
- if hash
101
- hash[field_type]
102
- end
103
- end
104
-
105
- private
106
-
107
- def process_custom_fields(json_data)
108
- custom_fields = json_data["custom_fields"]
109
- custom_fields.each do |field|
110
- process_custom_field(field)
111
- end
112
- end
113
-
114
- def process_custom_field(field)
115
- field_type_class = field["field_type_class"]
116
- field_type = field["field_type"]
117
- field_alias = field["field_alias"]
118
-
119
- process_custom_field_hash(@field_by_alias, field_type_class, field_alias, field_type)
120
- process_custom_field_hash(@alias_by_field, field_type_class, field_type, field_alias)
121
- end
122
-
123
- def process_custom_field_hash(hash, key1, key2, value)
124
- key1_hash = hash[key1]
125
- unless key1_hash
126
- key1_hash = {}
127
- hash[key1] = key1_hash
128
- end
129
- key1_hash[key2] = value
130
- end
131
-
132
- def process_properties(json_data)
133
- attribute_types = json_data["property_types"]
134
- attribute_values = json_data["property_values"]
135
- @properties = Properties.new(self, attribute_types, attribute_values)
136
- end
137
-
138
- def process_resources(json_data)
139
- attribute_types = json_data["resource_types"]
140
- resources = json_data["resources"]
141
- resources.each do |attribute_values|
142
- resource = Resource.new(self, attribute_types, attribute_values)
143
- @all_resources << resource
144
- @resources_by_unique_id[resource.unique_id] = resource
145
- @resources_by_id[resource.id] = resource
146
- end
147
- end
148
-
149
- def process_tasks(json_data)
150
- attribute_types = json_data["task_types"]
151
- tasks = json_data["tasks"]
152
- tasks.each do |attribute_values|
153
- task = Task.new(self, attribute_types, attribute_values)
154
- @all_tasks << task
155
- @tasks_by_unique_id[task.unique_id] = task
156
- @tasks_by_id[task.id] = task
157
- end
158
- end
159
-
160
- def process_assignments(json_data)
161
- attribute_types = json_data["assignment_types"]
162
- assignments = json_data["assignments"]
163
- assignments.each do |attribute_values|
164
- assignment = Assignment.new(self, attribute_types, attribute_values)
165
- @all_assignments << assignment
166
- if assignment.task
167
- assignment.task.assignments << assignment
168
- end
169
- if assignment.resource
170
- assignment.resource.assignments << assignment
171
- end
172
- end
173
- end
174
- end
175
- end
1
+ require 'json'
2
+
3
+ module MPXJ
4
+ # Represents a project plan
5
+ class Project
6
+ attr_reader :properties
7
+ attr_reader :all_resources
8
+ attr_reader :all_tasks
9
+ attr_reader :child_tasks
10
+ attr_reader :all_assignments
11
+ attr_reader :zone
12
+
13
+ def initialize(file_name, zone)
14
+ @resources_by_unique_id = {}
15
+ @tasks_by_unique_id = {}
16
+
17
+ @resources_by_id = {}
18
+ @tasks_by_id = {}
19
+
20
+ @all_resources = []
21
+ @all_tasks = []
22
+ @all_assignments = []
23
+ @child_tasks = []
24
+
25
+ @zone = zone
26
+
27
+ @field_by_alias = {}
28
+ @alias_by_field = {}
29
+
30
+ file = File.read(file_name)
31
+ json_data = JSON.parse(file)
32
+ process_custom_fields(json_data)
33
+ process_properties(json_data)
34
+ process_resources(json_data)
35
+ process_tasks(json_data)
36
+ process_assignments(json_data)
37
+ end
38
+
39
+ # Retrieves the resource with the matching unique_id attribute
40
+ #
41
+ # @param unique_id [Integer] resource unique ID
42
+ # @return [Resource] if the requested resource is found
43
+ # @return [nil] if the requested resource is not found
44
+ def get_resource_by_unique_id(unique_id)
45
+ @resources_by_unique_id[unique_id]
46
+ end
47
+
48
+ # Retrieves the task with the matching unique_id attribute
49
+ #
50
+ # @param unique_id [Integer] task unique ID
51
+ # @return [Task] if the requested task is found
52
+ # @return [nil] if the requested task is not found
53
+ def get_task_by_unique_id(unique_id)
54
+ @tasks_by_unique_id[unique_id]
55
+ end
56
+
57
+ # Retrieves the resource with the matching id attribute
58
+ #
59
+ # @param id [Integer] resource ID
60
+ # @return [Resource] if the requested resource is found
61
+ # @return [nil] if the requested resource is not found
62
+ def get_resource_by_id(id)
63
+ @resources_by_id[id]
64
+ end
65
+
66
+ # Retrieves the task with the matching id attribute
67
+ #
68
+ # @param id [Integer] task ID
69
+ # @return [Task] if the requested task is found
70
+ # @return [nil] if the requested task is not found
71
+ def get_task_by_id(id)
72
+ @tasks_by_unique_id[id]
73
+ end
74
+
75
+ # For a particular entity type (task, resource, and so on), retrieve
76
+ # the field which has the supplied alias. For example this allows the caller to
77
+ # answer the question "which task field is using the alias `Activity ID`"
78
+ #
79
+ # @param field_type_class[String] field type (possible values: task, resource, assignment, constraint, project)
80
+ # @param field_alias[String] the alias we want to look up
81
+ # @return [String] if the alias has been found return the name of the underlying field
82
+ # @return [nil] if the alias is not in use
83
+ def get_field_by_alias(field_type_class, field_alias)
84
+ hash = @field_by_alias[field_type_class]
85
+ if hash
86
+ hash[field_alias]
87
+ end
88
+ end
89
+
90
+ # For a particular entity type (task, resource, and so on), retrieve
91
+ # the alias used by the supplied field. For example this allows the caller to
92
+ # answer the question "does the task field Text1 have an alias?"
93
+ #
94
+ # @param field_type_class[String] field type (possible values: task, resource, assignment, constraint, project)
95
+ # @param field_type[String] the field type we want to look up
96
+ # @return [String] if the field has an alias, return the alias
97
+ # @return [nil] if the field does not have an alias
98
+ def get_alias_by_field(field_type_class, field_type)
99
+ hash = @alias_by_field[field_type_class]
100
+ if hash
101
+ hash[field_type]
102
+ end
103
+ end
104
+
105
+ private
106
+
107
+ def process_custom_fields(json_data)
108
+ custom_fields = json_data["custom_fields"]
109
+ custom_fields.each do |field|
110
+ process_custom_field(field)
111
+ end
112
+ end
113
+
114
+ def process_custom_field(field)
115
+ field_type_class = field["field_type_class"]
116
+ field_type = field["field_type"]
117
+ field_alias = field["field_alias"]
118
+
119
+ process_custom_field_hash(@field_by_alias, field_type_class, field_alias, field_type)
120
+ process_custom_field_hash(@alias_by_field, field_type_class, field_type, field_alias)
121
+ end
122
+
123
+ def process_custom_field_hash(hash, key1, key2, value)
124
+ key1_hash = hash[key1]
125
+ unless key1_hash
126
+ key1_hash = {}
127
+ hash[key1] = key1_hash
128
+ end
129
+ key1_hash[key2] = value
130
+ end
131
+
132
+ def process_properties(json_data)
133
+ attribute_types = json_data["property_types"]
134
+ attribute_values = json_data["property_values"]
135
+ @properties = Properties.new(self, attribute_types, attribute_values)
136
+ end
137
+
138
+ def process_resources(json_data)
139
+ attribute_types = json_data["resource_types"]
140
+ resources = json_data["resources"]
141
+ resources.each do |attribute_values|
142
+ resource = Resource.new(self, attribute_types, attribute_values)
143
+ @all_resources << resource
144
+ @resources_by_unique_id[resource.unique_id] = resource
145
+ @resources_by_id[resource.id] = resource
146
+ end
147
+ end
148
+
149
+ def process_tasks(json_data)
150
+ attribute_types = json_data["task_types"]
151
+ tasks = json_data["tasks"]
152
+ tasks.each do |attribute_values|
153
+ task = Task.new(self, attribute_types, attribute_values)
154
+ @all_tasks << task
155
+ @tasks_by_unique_id[task.unique_id] = task
156
+ @tasks_by_id[task.id] = task
157
+ end
158
+ end
159
+
160
+ def process_assignments(json_data)
161
+ attribute_types = json_data["assignment_types"]
162
+ assignments = json_data["assignments"]
163
+ assignments.each do |attribute_values|
164
+ assignment = Assignment.new(self, attribute_types, attribute_values)
165
+ @all_assignments << assignment
166
+ if assignment.task
167
+ assignment.task.assignments << assignment
168
+ end
169
+ if assignment.resource
170
+ assignment.resource.assignments << assignment
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
@@ -1,48 +1,48 @@
1
- require 'tempfile'
2
- require 'active_support/core_ext/time/calculations'
3
-
4
- module MPXJ
5
- # Used to read a project plan from a file
6
- class Reader
7
- # Reads a project plan from a file, and returns a Project instance
8
- # which provides access to the structure and attributes of the project data.
9
- # Note that an optional timezone can be supplied to ensue that all date-time
10
- # values returned are in the specified timezone.
11
- #
12
- # @param file_name [String] the name of the file to read
13
- # @param zone [ActiveSupport::TimeZone] an optional timezone
14
- # @return [Project] new Project instance
15
- def self.read(file_name, zone = nil)
16
- project = nil
17
- json_file = Tempfile.new([File.basename(file_name, ".*"), '.json'])
18
- tz = zone || Time.zone || ActiveSupport::TimeZone["UTC"]
19
-
20
- begin
21
- classpath = Dir["#{File.dirname(__FILE__)}/*.jar"].join(path_separator)
22
- java_output = `java -cp \"#{classpath}\" net.sf.mpxj.sample.MpxjConvert \"#{file_name}\" \"#{json_file.path}\"`
23
- if $?.exitstatus != 0
24
- raise "Failed to read file: #{java_output}"
25
- end
26
- project = Project.new(json_file, tz)
27
- ensure
28
- json_file.close
29
- json_file.unlink
30
- end
31
- project
32
- end
33
-
34
- # @private
35
- def self.path_separator
36
- if windows?
37
- ";"
38
- else
39
- ":"
40
- end
41
- end
42
-
43
- # @private
44
- def self.windows?
45
- (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
46
- end
47
- end
48
- end
1
+ require 'tempfile'
2
+ require 'active_support/core_ext/time/calculations'
3
+
4
+ module MPXJ
5
+ # Used to read a project plan from a file
6
+ class Reader
7
+ # Reads a project plan from a file, and returns a Project instance
8
+ # which provides access to the structure and attributes of the project data.
9
+ # Note that an optional timezone can be supplied to ensue that all date-time
10
+ # values returned are in the specified timezone.
11
+ #
12
+ # @param file_name [String] the name of the file to read
13
+ # @param zone [ActiveSupport::TimeZone] an optional timezone
14
+ # @return [Project] new Project instance
15
+ def self.read(file_name, zone = nil)
16
+ project = nil
17
+ json_file = Tempfile.new([File.basename(file_name, ".*"), '.json'])
18
+ tz = zone || Time.zone || ActiveSupport::TimeZone["UTC"]
19
+
20
+ begin
21
+ classpath = Dir["#{File.dirname(__FILE__)}/*.jar"].join(path_separator)
22
+ java_output = `java -cp \"#{classpath}\" net.sf.mpxj.sample.MpxjConvert \"#{file_name}\" \"#{json_file.path}\"`
23
+ if $?.exitstatus != 0
24
+ raise "Failed to read file: #{java_output}"
25
+ end
26
+ project = Project.new(json_file, tz)
27
+ ensure
28
+ json_file.close
29
+ json_file.unlink
30
+ end
31
+ project
32
+ end
33
+
34
+ # @private
35
+ def self.path_separator
36
+ if windows?
37
+ ";"
38
+ else
39
+ ":"
40
+ end
41
+ end
42
+
43
+ # @private
44
+ def self.windows?
45
+ (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
46
+ end
47
+ end
48
+ end
@@ -1,5 +1,5 @@
1
- # MPXJ gem module
2
- module MPXJ
3
- # MPXJ gem version number
4
- VERSION = "5.1.9"
5
- end
1
+ # MPXJ gem module
2
+ module MPXJ
3
+ # MPXJ gem version number
4
+ VERSION = "5.1.10"
5
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mpxj
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.1.9
4
+ version: 5.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Iles
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-08-30 00:00:00.000000000 Z
11
+ date: 2015-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler