nidyx 0.1.0
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.
- data/LICENSE +21 -0
- data/README.md +146 -0
- data/bin/nidyx +125 -0
- data/lib/nidyx/common.rb +54 -0
- data/lib/nidyx/core_ext/string.rb +12 -0
- data/lib/nidyx/generator.rb +17 -0
- data/lib/nidyx/mapper.rb +19 -0
- data/lib/nidyx/model.rb +12 -0
- data/lib/nidyx/objc/implementation.rb +33 -0
- data/lib/nidyx/objc/interface.rb +20 -0
- data/lib/nidyx/objc/mapper.rb +44 -0
- data/lib/nidyx/objc/model.rb +12 -0
- data/lib/nidyx/objc/model_base.rb +31 -0
- data/lib/nidyx/objc/property.rb +174 -0
- data/lib/nidyx/output.rb +25 -0
- data/lib/nidyx/parse_constants.rb +29 -0
- data/lib/nidyx/parser.rb +188 -0
- data/lib/nidyx/pointer.rb +17 -0
- data/lib/nidyx/property.rb +52 -0
- data/lib/nidyx/reader.rb +45 -0
- data/lib/nidyx/version.rb +3 -0
- data/lib/nidyx.rb +1 -0
- data/test/nidyx/core_ext/test_string.rb +40 -0
- data/test/nidyx/objc/test_model_base.rb +26 -0
- data/test/nidyx/objc/test_property.rb +237 -0
- data/test/nidyx/test_common.rb +102 -0
- data/test/nidyx/test_comparison.rb +64 -0
- data/test/nidyx/test_parser.rb +460 -0
- data/test/nidyx/test_pointer.rb +42 -0
- data/test/nidyx/test_property.rb +38 -0
- metadata +134 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Chris Knadler
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
# Nidyx 
|
2
|
+
|
3
|
+
[JSON Schema][JSONSchema] ⇒ Model.
|
4
|
+
|
5
|
+
Nidyx generates Objective-C models from JSON Schema. It can also generate
|
6
|
+
models with [JSONModel](https://github.com/icanzilb/JSONModel) support.
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
```
|
11
|
+
usage: nidyx [-h] [--version]
|
12
|
+
nidyx <schema> <class-prefix> [output-directory]
|
13
|
+
[-j] [-n] [-a author] [-c company] [-p project]
|
14
|
+
|
15
|
+
-a, --author AUTHOR Author's name
|
16
|
+
-c, --company COMPANY Company's name
|
17
|
+
-p, --project PROJECT Project's name
|
18
|
+
-j, --json-model Generate with JSONModel support
|
19
|
+
-n, --no-comments Generate without header comments
|
20
|
+
-h, --help Print usage information
|
21
|
+
--version Print version
|
22
|
+
|
23
|
+
Nidyx generates plain Objective-C models from JSON Schema. It can also generate
|
24
|
+
models with JSONModel support.
|
25
|
+
|
26
|
+
Examples
|
27
|
+
========
|
28
|
+
|
29
|
+
Bare minimum. Given a schema and a class prefix, generate models in the
|
30
|
+
current directory:
|
31
|
+
|
32
|
+
$ nidyx example.json.schema ClassPrefix
|
33
|
+
|
34
|
+
Specify an ouput directory:
|
35
|
+
|
36
|
+
$ nidyx example.json.schema ClassPrefix /path/to/output/directory
|
37
|
+
|
38
|
+
Generate models with JSONModel support and all optional documentation:
|
39
|
+
|
40
|
+
$ nidyx example.json.schema ClassPrefix /path/to/output/directory \
|
41
|
+
-j -a "Your Name" -c "Company Name" -p "Project Name"
|
42
|
+
|
43
|
+
```
|
44
|
+
|
45
|
+
## Features
|
46
|
+
|
47
|
+
__[JSON Schema draft 4][JSONSchemaDraft4] support:__
|
48
|
+
|
49
|
+
Nidyx exclusively supports JSON Schema draft 4. All previous drafts are not
|
50
|
+
supported intentionally.
|
51
|
+
|
52
|
+
## Examples
|
53
|
+
|
54
|
+
Examples are run with the following unless otherwise specified:
|
55
|
+
|
56
|
+
```bash
|
57
|
+
$ nidyx example.json.schema Example
|
58
|
+
```
|
59
|
+
|
60
|
+
#### Simple Properties
|
61
|
+
|
62
|
+
```json
|
63
|
+
{
|
64
|
+
"properties": {
|
65
|
+
"key": { "type": "string" },
|
66
|
+
"value": { "type": "string" }
|
67
|
+
}
|
68
|
+
}
|
69
|
+
```
|
70
|
+
|
71
|
+
```objc
|
72
|
+
// ExampleModel.h
|
73
|
+
@interface ExampleModel
|
74
|
+
@property (strong, nonatomic) NSString* key;
|
75
|
+
@property (strong, nonatomic) NSString* value;
|
76
|
+
@end
|
77
|
+
```
|
78
|
+
|
79
|
+
#### Refs and Nested Properties
|
80
|
+
|
81
|
+
```json
|
82
|
+
{
|
83
|
+
"properties": {
|
84
|
+
"id": {
|
85
|
+
"type": "object",
|
86
|
+
"properties": {
|
87
|
+
"key": { "type": "string" },
|
88
|
+
"hash": { "type": "string" }
|
89
|
+
}
|
90
|
+
},
|
91
|
+
"value": { "$ref": "#/definitions/obj" }
|
92
|
+
},
|
93
|
+
"definitions": {
|
94
|
+
"obj": {
|
95
|
+
"type": "object",
|
96
|
+
"properties": {
|
97
|
+
"banner": { "$ref": "#/definitions/banner" },
|
98
|
+
"name": { "type": "string" },
|
99
|
+
"count": { "type": "integer" }
|
100
|
+
}
|
101
|
+
},
|
102
|
+
"banner": { "type": "string" }
|
103
|
+
}
|
104
|
+
}
|
105
|
+
```
|
106
|
+
|
107
|
+
```objc
|
108
|
+
// ExampleModel.h
|
109
|
+
#import "ExampleIdModel.h"
|
110
|
+
#import "ExampleObjModel.h"
|
111
|
+
@interface ExampleModel
|
112
|
+
@property (strong, nonatomic) ExampleIdModel* id;
|
113
|
+
@property (strong, nonatomic) ExampleObjModel* value;
|
114
|
+
@end
|
115
|
+
|
116
|
+
// ExampleIdModel.h
|
117
|
+
@interface ExampleIdModel
|
118
|
+
@property (strong, nonatomic) NSString* key;
|
119
|
+
@property (strong, nonatomic) NSString* hash;
|
120
|
+
@end
|
121
|
+
|
122
|
+
// ExampleObjModel.h
|
123
|
+
@interface ExampleObjModel
|
124
|
+
@property (strong, nonatomic) NSString* banner;
|
125
|
+
@property (strong, nonatomic) NSString* name;
|
126
|
+
@property (assign, nonatomic) NSInteger count;
|
127
|
+
@end
|
128
|
+
```
|
129
|
+
|
130
|
+
#### Caveats
|
131
|
+
|
132
|
+
* The following is omitted from the beginning of all JSON examples:
|
133
|
+
|
134
|
+
```
|
135
|
+
"$schema": "http://json-schema.org/draft-04/schema#",
|
136
|
+
"type": "object",
|
137
|
+
```
|
138
|
+
|
139
|
+
* `.m` files are also omitted from all examples
|
140
|
+
|
141
|
+
## License
|
142
|
+
|
143
|
+
MIT.
|
144
|
+
|
145
|
+
[JSONSchema]: http://json-schema.org/
|
146
|
+
[JSONSchemaDraft4]: http://tools.ietf.org/html/draft-zyp-json-schema-04
|
data/bin/nidyx
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require "nidyx"
|
5
|
+
require "nidyx/version"
|
6
|
+
require "nidyx/generator"
|
7
|
+
|
8
|
+
###
|
9
|
+
# help text
|
10
|
+
###
|
11
|
+
|
12
|
+
BANNER = <<END
|
13
|
+
usage: nidyx [-h] [--version]
|
14
|
+
nidyx <schema> <class-prefix> [output-directory]
|
15
|
+
[-n] [-a author] [-c company] [-p project]
|
16
|
+
[--json-model] # objc specific
|
17
|
+
|
18
|
+
END
|
19
|
+
|
20
|
+
DESC = <<END
|
21
|
+
|
22
|
+
Nidyx generates plain Objective-C models from JSON Schema. It can also generate
|
23
|
+
models with JSONModel support.
|
24
|
+
|
25
|
+
Examples
|
26
|
+
========
|
27
|
+
|
28
|
+
Bare minimum. Given a schema and a class prefix, generate models in the
|
29
|
+
current directory:
|
30
|
+
|
31
|
+
$ nidyx example.json.schema ClassPrefix
|
32
|
+
|
33
|
+
Specify an ouput directory:
|
34
|
+
|
35
|
+
$ nidyx example.json.schema ClassPrefix /path/to/output/directory
|
36
|
+
|
37
|
+
Generate models with JSONModel support and all optional documentation:
|
38
|
+
|
39
|
+
$ nidyx example.json.schema ClassPrefix /path/to/output/directory \\
|
40
|
+
-j -a "Your Name" -c "Company Name" -p "Project Name"
|
41
|
+
|
42
|
+
END
|
43
|
+
|
44
|
+
###
|
45
|
+
# option parsing
|
46
|
+
###
|
47
|
+
|
48
|
+
# defaults
|
49
|
+
options = {
|
50
|
+
:comments => true,
|
51
|
+
:platform => "objc",
|
52
|
+
:objc => {
|
53
|
+
:json_model => false
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
opts = OptionParser.new do |o|
|
58
|
+
o.banner = BANNER
|
59
|
+
|
60
|
+
###
|
61
|
+
# general generation options
|
62
|
+
###
|
63
|
+
|
64
|
+
o.on("-a", "--author AUTHOR", "Author's name") do |a|
|
65
|
+
options[:author] = a
|
66
|
+
end
|
67
|
+
|
68
|
+
o.on("-c", "--company COMPANY", "Company's name") do |c|
|
69
|
+
options[:company] = c
|
70
|
+
end
|
71
|
+
|
72
|
+
o.on("-p", "--project PROJECT", "Project's name") do |p|
|
73
|
+
options[:project] = p
|
74
|
+
end
|
75
|
+
|
76
|
+
o.on("-n", "--no-comments", "Generate without header comments") do |n|
|
77
|
+
options[:comments] = false
|
78
|
+
end
|
79
|
+
|
80
|
+
###
|
81
|
+
# objc generation options
|
82
|
+
###
|
83
|
+
|
84
|
+
o.on("--json-model", "Generate with JSONModel support") do |j|
|
85
|
+
options[:objc][:json_model] = true
|
86
|
+
end
|
87
|
+
|
88
|
+
###
|
89
|
+
# other
|
90
|
+
###
|
91
|
+
|
92
|
+
o.on("-h", "--help", "Print usage information") do
|
93
|
+
puts o
|
94
|
+
exit
|
95
|
+
end
|
96
|
+
|
97
|
+
o.on("--version", "Print version") do
|
98
|
+
puts Nidyx::VERSION
|
99
|
+
exit
|
100
|
+
end
|
101
|
+
|
102
|
+
o.separator DESC
|
103
|
+
end
|
104
|
+
|
105
|
+
begin
|
106
|
+
opts.parse!
|
107
|
+
rescue OptionParser::InvalidOption => e
|
108
|
+
puts e
|
109
|
+
puts opts
|
110
|
+
exit 1
|
111
|
+
end
|
112
|
+
|
113
|
+
if ARGV.size < 2
|
114
|
+
puts "Too few arguments." unless ARGV.empty?
|
115
|
+
puts opts
|
116
|
+
exit 1
|
117
|
+
end
|
118
|
+
|
119
|
+
options[:output_path] = ARGV[2]
|
120
|
+
|
121
|
+
###
|
122
|
+
# run
|
123
|
+
###
|
124
|
+
|
125
|
+
Nidyx::Generator.run(ARGV[0], ARGV[1], options)
|
data/lib/nidyx/common.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module Nidyx
|
2
|
+
module Common
|
3
|
+
class NoObjectAtPathError < StandardError; end
|
4
|
+
|
5
|
+
CLASS_SUFFIX = "Model"
|
6
|
+
IGNORED_KEYS = "properties", "definitions"
|
7
|
+
|
8
|
+
def class_name(prefix, key)
|
9
|
+
if key
|
10
|
+
prefix + key.camelize + CLASS_SUFFIX
|
11
|
+
else
|
12
|
+
prefix + CLASS_SUFFIX
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def class_name_from_path(prefix, path, schema)
|
17
|
+
override = object_at_path(path, schema)[NAME_OVERRIDE_KEY]
|
18
|
+
return class_name(prefix, override.camelize) if override
|
19
|
+
|
20
|
+
name = ""
|
21
|
+
path.each_index do |idx|
|
22
|
+
# skip ignored keys such as "properties" in the name
|
23
|
+
next if IGNORED_KEYS.include?(path[idx])
|
24
|
+
# skip the last key if we are using an override
|
25
|
+
next if override && (idx == path.length - 1)
|
26
|
+
|
27
|
+
obj = object_at_path(path[0..idx], schema)
|
28
|
+
if obj[NAME_OVERRIDE_KEY]
|
29
|
+
name << obj[NAME_OVERRIDE_KEY].camelize
|
30
|
+
else
|
31
|
+
name << path[idx].camelize
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# append the override name to the end if present
|
36
|
+
name << override.camelize if override
|
37
|
+
class_name(prefix, name)
|
38
|
+
end
|
39
|
+
|
40
|
+
def object_at_path(path, schema)
|
41
|
+
obj = schema
|
42
|
+
|
43
|
+
begin
|
44
|
+
path.each { |p| obj = obj[p] }
|
45
|
+
rescue
|
46
|
+
raise NoObjectAtPathError, path
|
47
|
+
end
|
48
|
+
|
49
|
+
raise NoObjectAtPathError, path unless obj
|
50
|
+
|
51
|
+
obj
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class String
|
2
|
+
# Inspired by (read: "Stolen from") Rails ActiveSupport::Inflector
|
3
|
+
def camelize(uppercase_first_letter = true)
|
4
|
+
s = self
|
5
|
+
if uppercase_first_letter
|
6
|
+
s = s.sub(/^[a-z\d]*/) { $&.capitalize }
|
7
|
+
else
|
8
|
+
s = s.sub(/^([A-Z_]|\w)/) { $&.downcase }
|
9
|
+
end
|
10
|
+
s.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'nidyx/reader'
|
2
|
+
require 'nidyx/parser'
|
3
|
+
require 'nidyx/mapper'
|
4
|
+
require 'nidyx/output'
|
5
|
+
|
6
|
+
module Nidyx
|
7
|
+
module Generator
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def run(schema_path, model_prefix, options)
|
11
|
+
schema = Nidyx::Reader.read(schema_path)
|
12
|
+
raw_models = Nidyx::Parser.parse(model_prefix, schema, options)
|
13
|
+
models = Nidyx::Mapper.map(raw_models, options)
|
14
|
+
Nidyx::Output.write(models, options[:output_path])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/nidyx/mapper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'nidyx/objc/mapper'
|
2
|
+
|
3
|
+
module Nidyx
|
4
|
+
module Mapper
|
5
|
+
extend self
|
6
|
+
|
7
|
+
# Proxies model mapping to the proper platform mapper
|
8
|
+
# @param models [Hash] a hash with model name keys and Model values
|
9
|
+
# @param options [Hash] runtime options
|
10
|
+
# @return [Array] an array of models generated for a specific platform
|
11
|
+
def map(models, options)
|
12
|
+
models = models.values
|
13
|
+
case options[:platform].downcase
|
14
|
+
when "objc", "obj-c", "objective-c"
|
15
|
+
Nidyx::ObjCMapper.map(models, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/nidyx/model.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require "nidyx/objc/model_base"
|
2
|
+
|
3
|
+
module Nidyx
|
4
|
+
class ObjCImplementation < ObjCModelBase
|
5
|
+
self.template_file = File.join(self.template_path, "implementation.mustache")
|
6
|
+
|
7
|
+
attr_accessor :name_overrides
|
8
|
+
|
9
|
+
def initialize(name, options)
|
10
|
+
super
|
11
|
+
self.file_name = "#{name}.#{EXT}"
|
12
|
+
self.imports = [name]
|
13
|
+
end
|
14
|
+
|
15
|
+
def name_overrides?
|
16
|
+
!self.name_overrides.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def name_override_string
|
20
|
+
string = ""
|
21
|
+
count = 0
|
22
|
+
name_overrides.each do |original, override|
|
23
|
+
count += 1
|
24
|
+
string += "@\"#{original}\": @\"#{override}\""
|
25
|
+
string += ",\n" unless count == name_overrides.length
|
26
|
+
end
|
27
|
+
string
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
EXT = "m"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "nidyx/objc/model_base"
|
2
|
+
|
3
|
+
module Nidyx
|
4
|
+
class ObjCInterface < ObjCModelBase
|
5
|
+
attr_accessor :properties
|
6
|
+
|
7
|
+
self.template_file = File.join(self.template_path, "interface.mustache")
|
8
|
+
|
9
|
+
def initialize(name, options)
|
10
|
+
super
|
11
|
+
self.file_name = "#{name}.#{EXT}"
|
12
|
+
self.imports << JSON_MODEL_IMPORT if self.json_model
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
EXT = "h"
|
17
|
+
JSON_MODEL_IMPORT = "JSONModel"
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "set"
|
2
|
+
require "nidyx/objc/model"
|
3
|
+
require "nidyx/objc/interface"
|
4
|
+
require "nidyx/objc/implementation"
|
5
|
+
require "nidyx/objc/property"
|
6
|
+
|
7
|
+
module Nidyx
|
8
|
+
module ObjCMapper
|
9
|
+
extend self
|
10
|
+
|
11
|
+
# Generates a list of ObjCModels
|
12
|
+
# @param models [Array] an array of generic Models to map
|
13
|
+
# @param options [Hash] runtime options
|
14
|
+
# @return [Array] a list of ObjCModels
|
15
|
+
def map(models, options)
|
16
|
+
objc_models = []
|
17
|
+
|
18
|
+
models.each do |m|
|
19
|
+
interface = map_interface(m, options)
|
20
|
+
implementation = map_implementation(m, options)
|
21
|
+
objc_models << Nidyx::ObjCModel.new(interface, implementation)
|
22
|
+
end
|
23
|
+
|
24
|
+
objc_models
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def map_interface(model, options)
|
30
|
+
interface = Nidyx::ObjCInterface.new(model.name, options)
|
31
|
+
interface.properties = model.properties.map { |p| Nidyx::ObjCProperty.new(p) }
|
32
|
+
interface.imports += model.dependencies.to_a
|
33
|
+
interface
|
34
|
+
end
|
35
|
+
|
36
|
+
def map_implementation(model, options)
|
37
|
+
implementation = Nidyx::ObjCImplementation.new(model.name, options)
|
38
|
+
name_overrides = {}
|
39
|
+
model.properties.each { |p| name_overrides[p.overriden_name] = p.name if p.overriden_name }
|
40
|
+
implementation.name_overrides = name_overrides
|
41
|
+
implementation
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "mustache"
|
2
|
+
|
3
|
+
module Nidyx
|
4
|
+
class ObjCModelBase < Mustache
|
5
|
+
attr_accessor :name, :file_name, :author, :owner, :project, :imports, :comments, :json_model
|
6
|
+
|
7
|
+
self.template_path = File.join(__FILE__, "../../../../templates/objc")
|
8
|
+
|
9
|
+
def initialize(name, options)
|
10
|
+
@name = name
|
11
|
+
@author = options[:author]
|
12
|
+
@owner = options[:company]
|
13
|
+
@project = options[:project]
|
14
|
+
@comments = options[:comments]
|
15
|
+
@json_model = options[:objc][:json_model] if options[:objc]
|
16
|
+
@imports = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def has_imports?
|
20
|
+
!self.imports.empty?
|
21
|
+
end
|
22
|
+
|
23
|
+
def no_owner?
|
24
|
+
!self.owner
|
25
|
+
end
|
26
|
+
|
27
|
+
def json_model?
|
28
|
+
self.json_model
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|