mpxj 5.1.9 → 5.1.10

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 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