├── US2MapperKit
├── Shared Test Cases
│ ├── Classes
│ │ ├── TestObjectFive.swift
│ │ ├── TestObjectFour.swift
│ │ ├── TestObjectNine.swift
│ │ ├── TestObjectSix.swift
│ │ ├── TestObjectTen.swift
│ │ ├── TestObjectTwo.swift
│ │ ├── TestObjectEight.swift
│ │ ├── TestObjectEleven.swift
│ │ ├── TestObjectSeven.swift
│ │ ├── TestObjectThree.swift
│ │ ├── TestObjectTwelve.swift
│ │ ├── TestObjectThirteen.swift
│ │ ├── Internal
│ │ │ ├── _TestObjectOne.swift
│ │ │ ├── _TestObjectTwo.swift
│ │ │ ├── _TestObjectFive.swift
│ │ │ ├── _TestObjectSeven.swift
│ │ │ ├── _TestObjectSix.swift
│ │ │ ├── _TestObjectEight.swift
│ │ │ ├── _TestObjectThirteen.swift
│ │ │ ├── US2Instantiator.swift
│ │ │ ├── _TestObjectFour.swift
│ │ │ ├── _TestObjectEleven.swift
│ │ │ ├── _TestObjectThree.swift
│ │ │ ├── _TestObjectTwelve.swift
│ │ │ ├── _TestObjectNine.swift
│ │ │ └── _TestObjectTen.swift
│ │ └── TestObjectOne.swift
│ ├── Mapping
│ │ ├── TestObjectTwo.plist
│ │ ├── TestObjectFive.plist
│ │ ├── TestObjectSeven.plist
│ │ ├── TestObjectEight.plist
│ │ ├── TestObjectSix.plist
│ │ ├── TestObjectThirteen.plist
│ │ ├── TestObjectFour.plist
│ │ ├── TestObjectNine.plist
│ │ ├── TestObjectTwelve.plist
│ │ ├── TestObjectTen.plist
│ │ ├── TestObjectEleven.plist
│ │ └── TestObjectThree.plist
│ └── Test Case Objects
│ │ ├── ValueTypeDefinitions.swift
│ │ ├── US2ExampleEnumTransformer.swift
│ │ ├── US2ExampleTupleTransformer.swift
│ │ ├── US2ExampleStructTransformer.swift
│ │ └── US2ExampleClosureTransformer.swift
└── US2MapperKit
│ ├── US2MapperKitOSX
│ ├── US2MapperKitOSX.h
│ └── Info.plist
│ ├── US2MapperKitiOS
│ ├── US2MapperKitiOS.h
│ └── Info.plist
│ ├── US2MapperKitOSXTests
│ └── Info.plist
│ ├── US2MapperKitiOSTests
│ └── Info.plist
│ └── US2MapperKit.xcodeproj
│ └── xcshareddata
│ └── xcschemes
│ ├── US2MapperKit - OSX.xcscheme
│ └── US2MapperKit - iOS.xcscheme
├── documentation
├── readme_assets
│ ├── debug_flag.png
│ ├── closure_example.png
│ ├── location_plist.png
│ ├── mapperkit_header.png
│ ├── basic_concept_image.png
│ ├── enum_example_plist.png
│ ├── struct_example_plist.png
│ ├── transformer_example.png
│ ├── default_value_example.png
│ ├── nested_mapping_example.png
│ ├── non_optional_business.png
│ ├── ratings_array_example.png
│ ├── tuple_mapping_example.png
│ ├── basic data_types_business.png
│ ├── business_location_example.png
│ └── transformer_fullname_example.png
├── default_values.md
├── compatibility_issues.md
├── troubleshooting.md
├── enable_debug_mode.md
├── nested_mapping.md
├── changelog.md
├── complex_value_types.md
├── non_optional_value_types.md
├── collection_types.md
├── custom_transforms_tuples.md
├── custom_transforms_struct.md
├── custom_transforms_enums.md
├── custom_transforms.md
├── custom_transforms_closures.md
├── optional_value_types.md
└── installation.md
├── .gitignore
├── Source
├── US2MapperKit
│ ├── Parsers
│ │ ├── ComplexTypeParser.swift
│ │ ├── NativeValueArrayParser.swift
│ │ ├── NativeValueDictionaryParser.swift
│ │ ├── ComplexValueArrayParser.swift
│ │ ├── NativeTypeParser.swift
│ │ ├── ComplexValueDictionaryParser.swift
│ │ ├── CollectionParser.swift
│ │ └── Parser.swift
│ ├── US2CompoundValueTransformer.swift
│ ├── Transformer
│ │ └── Transformer.swift
│ ├── Validator
│ │ └── Validator.swift
│ └── US2Mapper.swift
└── ModelScript
│ └── modelgen-swift.py
├── US2MapperKit.podspec
├── LICENSE.txt
└── README.md
/US2MapperKit/Shared Test Cases/Classes/TestObjectFive.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectFive : _TestObjectFive {
4 |
5 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectFour.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectFour : _TestObjectFour {
4 |
5 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectNine.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectNine : _TestObjectNine {
4 |
5 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectSix.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectSix : _TestObjectSix {
4 |
5 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectTen.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectTen : _TestObjectTen {
4 |
5 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectTwo.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectTwo : _TestObjectTwo {
4 |
5 | }
--------------------------------------------------------------------------------
/documentation/readme_assets/debug_flag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/debug_flag.png
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectEight.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectEight : _TestObjectEight {
4 |
5 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectEleven.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectEleven : _TestObjectEleven {
4 |
5 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectSeven.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectSeven : _TestObjectSeven {
4 |
5 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectThree.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectThree : _TestObjectThree {
4 |
5 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectTwelve.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectTwelve : _TestObjectTwelve {
4 |
5 | }
--------------------------------------------------------------------------------
/documentation/readme_assets/closure_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/closure_example.png
--------------------------------------------------------------------------------
/documentation/readme_assets/location_plist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/location_plist.png
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectThirteen.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | class TestObjectThirteen : _TestObjectThirteen {
4 |
5 | }
--------------------------------------------------------------------------------
/documentation/readme_assets/mapperkit_header.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/mapperkit_header.png
--------------------------------------------------------------------------------
/documentation/readme_assets/basic_concept_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/basic_concept_image.png
--------------------------------------------------------------------------------
/documentation/readme_assets/enum_example_plist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/enum_example_plist.png
--------------------------------------------------------------------------------
/documentation/readme_assets/struct_example_plist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/struct_example_plist.png
--------------------------------------------------------------------------------
/documentation/readme_assets/transformer_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/transformer_example.png
--------------------------------------------------------------------------------
/documentation/readme_assets/default_value_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/default_value_example.png
--------------------------------------------------------------------------------
/documentation/readme_assets/nested_mapping_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/nested_mapping_example.png
--------------------------------------------------------------------------------
/documentation/readme_assets/non_optional_business.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/non_optional_business.png
--------------------------------------------------------------------------------
/documentation/readme_assets/ratings_array_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/ratings_array_example.png
--------------------------------------------------------------------------------
/documentation/readme_assets/tuple_mapping_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/tuple_mapping_example.png
--------------------------------------------------------------------------------
/documentation/readme_assets/basic data_types_business.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/basic data_types_business.png
--------------------------------------------------------------------------------
/documentation/readme_assets/business_location_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/business_location_example.png
--------------------------------------------------------------------------------
/documentation/readme_assets/transformer_fullname_example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ustwo/US2MapperKit/HEAD/documentation/readme_assets/transformer_fullname_example.png
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectTwo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectOne.swift:
--------------------------------------------------------------------------------
1 | //
2 | // _TestObjectOne.swift
3 | // US2Mapper
4 | //
5 | // Created by Anton Doudarev on 6/25/15.
6 | // Copyright © 2015 US2Mapper. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class TestObjectOne : _TestObjectOne {
12 |
13 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | .DS_Store
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | *.xcworkspace
13 | !default.xcworkspace
14 | xcuserdata
15 | profile
16 | *.moved-aside
17 | DerivedData
18 | .idea/
19 | xcuserdata/
20 | UserInterfaceState.xcuserstate
21 | # Pods - for those of you who use CocoaPods
22 | Pods
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Test Case Objects/ValueTypeDefinitions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Structs.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton on 9/2/15.
6 | // Copyright (c) 2015 ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct StructExample {
12 | var string1: String
13 | var string2: String
14 | }
15 |
16 | enum EnumExample : Int {
17 | case One = 1, Two, Three, Four, Five
18 | }
--------------------------------------------------------------------------------
/documentation/default_values.md:
--------------------------------------------------------------------------------
1 | ##Example - Defining Default Values
2 | When there is need to fallback to a default value for optional or non-optional properties, define a default value by appending **default** to the property definition in the model mapping. In the example below, if the response dictionary does not have a value for the **open** property while mapping, it will default to false.
3 |
4 | **Business.plist**
5 |
6 |
7 | 
8 |
9 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Test Case Objects/US2ExampleEnumTransformer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // US2ExampleEnumTransformer.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton on 9/3/15.
6 | // Copyright (c) 2015 ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public class US2ExampleEnumTransformer : US2TransformerProtocol {
12 | public func transformValues(inputValues : Dictionary?) -> Any? {
13 |
14 | if let enumValue = inputValues!["enumValue"] as? Int {
15 | return EnumExample(rawValue : enumValue)!
16 | }
17 |
18 | return nil
19 | }
20 | }
21 |
22 |
23 |
--------------------------------------------------------------------------------
/US2MapperKit/US2MapperKit/US2MapperKitOSX/US2MapperKitOSX.h:
--------------------------------------------------------------------------------
1 | //
2 | // US2MapperKitOSX.h
3 | // US2MapperKitOSX
4 | //
5 | // Created by Anton Doudarev on 7/10/15.
6 | // Copyright (c) 2015 ustwo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for US2MapperKitOSX.
12 | FOUNDATION_EXPORT double US2MapperKitOSXVersionNumber;
13 |
14 | //! Project version string for US2MapperKitOSX.
15 | FOUNDATION_EXPORT const unsigned char US2MapperKitOSXVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/US2MapperKit/US2MapperKit/US2MapperKitiOS/US2MapperKitiOS.h:
--------------------------------------------------------------------------------
1 | //
2 | // US2MapperKitiOS.h
3 | // US2MapperKitiOS
4 | //
5 | // Created by Anton Doudarev on 7/10/15.
6 | // Copyright (c) 2015 ustwo. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for US2MapperKitiOS.
12 | FOUNDATION_EXPORT double US2MapperKitiOSVersionNumber;
13 |
14 | //! Project version string for US2MapperKitiOS.
15 | FOUNDATION_EXPORT const unsigned char US2MapperKitiOSVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectFive.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalSubType
6 |
7 | key
8 | optional_subtype
9 | type
10 | TestObjectThree
11 |
12 | non_optionalSubType
13 |
14 | nonoptional
15 | true
16 | key
17 | non_optional_subtype
18 | type
19 | TestObjectThree
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/documentation/compatibility_issues.md:
--------------------------------------------------------------------------------
1 | ##US2MapperKit - Compatibility Issues
2 |
3 | ####Carthage Issues: Module Created by Older Version of The Compiler
4 |
5 | This framework was designed to run with Swift 1.2 and 2.0. When installing using Carthage, the environment needs to be pointed to the correct instance of Xcode for the module to build correctly.
6 |
7 | If using the **Current SDK 6.0+** (Swift 1.2), run the following command in the terminal:
8 |
9 | ```
10 | sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
11 | ```
12 |
13 | If using the **Beta SDK 7.0+** (Swift 2.0), run the following command in the terminal:
14 |
15 | ```
16 | sudo xcode-select -s /Applications/Xcode-beta.app/Contents/Developer
17 | ```
18 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Test Case Objects/US2ExampleTupleTransformer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // US2ExampleTupleTransformer.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton on 9/3/15.
6 | // Copyright (c) 2015 ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public class US2ExampleTupleTransformer : US2TransformerProtocol {
12 | public func transformValues(inputValues : Dictionary?) -> Any? {
13 |
14 | if let valueOne = inputValues!["value_one"] as? Double {
15 | if let valueTwo = inputValues!["value_two"] as? Double {
16 | return (val1 : valueOne, val2 : valueTwo)
17 | }
18 | }
19 |
20 | return nil
21 | }
22 | }
--------------------------------------------------------------------------------
/Source/US2MapperKit/Parsers/ComplexTypeParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ComplexTypeParser.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class ComplexTypeParser {
12 |
13 | // MARK Maps a dictionary to a complex type
14 |
15 | class func complexObject(fromValue data : Dictionary, ofType objectType : String?, using instantiator : US2InstantiatorProtocol) -> AnyObject? {
16 | if let complexTypeValue: AnyObject = instantiator.newInstance(ofType: objectType!, withValue: data) {
17 | return complexTypeValue
18 | }
19 |
20 | return nil
21 | }
22 | }
--------------------------------------------------------------------------------
/documentation/troubleshooting.md:
--------------------------------------------------------------------------------
1 | ##US2MapperKit - Known Compatibility Issues
2 |
3 | ####Carthage Issues: Module Created by Older Version of The Compiler
4 |
5 | This framework was designed to run with Swift 1.2 and 2.0 accordingly. When installing using Carthage, the environment needs to be pointing to the correct instance of Xcode for the module to build correctly.
6 |
7 | If using the **Current SDK 6.0+** (Swift 1.2) run the following command in the terminal:
8 |
9 | ```
10 | sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
11 | ```
12 |
13 | If using the **Beta SDK 7.0+** (Swift 2.0) run the following command in the terminal:
14 |
15 | ```
16 | sudo xcode-select -s /Applications/Xcode-beta.app/Contents/Developer
17 | ```
18 |
--------------------------------------------------------------------------------
/US2MapperKit.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "US2MapperKit"
3 | s.version = "0.2.0"
4 | s.summary = "JSON/Dictionary response driven object mapper with support for Swift 1.2 / 2.0"
5 | s.homepage = "https://github.com/ustwo/US2MapperKit"
6 | s.license = 'MIT'
7 | s.author = { "Anton Doudarev" => "anton@ustwo.com" }
8 | s.source = { :git => 'https://github.com/ustwo/US2MapperKit.git', :tag => s.version }
9 | s.ios.deployment_target = '8.0'
10 | s.osx.deployment_target = '10.9'
11 | s.source_files = "Source/US2MapperKit/*.*", "Source/US2MapperKit/Parsers/*.*", "Source/US2MapperKit/Transformer/*.*", "Source/US2MapperKit/Validator/*.*", "Source/ModelScript/*.*"
12 | s.requires_arc = true
13 | end
14 |
--------------------------------------------------------------------------------
/Source/US2MapperKit/US2CompoundValueTransformer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // US2CompoundValueTransformer.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 6/29/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | public class US2CompoundValueTransformer : US2TransformerProtocol {
10 |
11 | public func transformValues(inputValues : Dictionary?) -> Any? {
12 | var outputString : String = ""
13 |
14 | if let stringDictionary = inputValues as? Dictionary {
15 | for (key, value) in stringDictionary {
16 | outputString += value
17 | }
18 | }
19 |
20 | if outputString.isEmpty { return nil }
21 | return outputString
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectSeven.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalArrayType
6 |
7 | key
8 | optional_sub_object_array
9 | type
10 | Array
11 | collection_subtype
12 | TestObjectFour
13 |
14 | non_optionalArrayType
15 |
16 | nonoptional
17 | true
18 | key
19 | non_optional_sub_object_array
20 | type
21 | Array
22 | collection_subtype
23 | TestObjectFour
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Test Case Objects/US2ExampleStructTransformer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // US2ExampleStructTransformer.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton on 9/2/15.
6 | // Copyright (c) 2015 ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public class US2ExampleStructTransformer : US2TransformerProtocol {
12 | public func transformValues(inputValues : Dictionary?) -> Any? {
13 |
14 | if let stringDictionary = inputValues as? Dictionary {
15 | if let string1 = stringDictionary["string1"] {
16 | if let string2 = stringDictionary["string2"] {
17 | return StructExample(string1 : string1, string2 : string2)
18 | }
19 | }
20 | }
21 |
22 | return nil
23 | }
24 | }
--------------------------------------------------------------------------------
/documentation/enable_debug_mode.md:
--------------------------------------------------------------------------------
1 | ##Example - Enable Debug Mode
2 |
3 | It is not always feasible to know why a a fail-able initializer may have failed to parse a response. USMapperKit provides the ability to use a build-time flag to print out failures to the console.
4 |
5 | To enable Debug mode, add the **-DUS2MAPPER_DEBUG** flag to the **Other Swift Flags** in your build settings.
6 |
7 |
8 | 
9 |
10 |
11 | The resulting output in the console will resemble the following:
12 |
13 | ```
14 | Business instance could not be parsed, missing values for the following non-optional properties:
15 | - business_uuid
16 |
17 | Response:
18 | [response: {
19 | "business_name" : "UsTwoRestaurant";
20 | "business_ratings" : [ 5, 4, 5, 4 ];
21 | "business_open" : 1;
22 | }]
23 |
24 | ```
25 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectEight.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalDictionaryType
6 |
7 | key
8 | optional_sub_object_dictionary
9 | type
10 | Dictionary
11 | collection_subtype
12 | TestObjectFour
13 |
14 | non_optionalDictionaryType
15 |
16 | nonoptional
17 | true
18 | key
19 | non_optional_sub_object_dictionary
20 | type
21 | Dictionary
22 | collection_subtype
23 | TestObjectFour
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/US2MapperKit/US2MapperKit/US2MapperKitOSXTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.ustwo.US2MapperKitOSXTests
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/US2MapperKit/US2MapperKit/US2MapperKitiOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.ustwo.US2MapperKitiOSTests
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/US2MapperKit/US2MapperKit/US2MapperKitiOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.ustwo.US2MapperKit
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectSix.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalCompoundString
6 |
7 | key
8 |
9 | left_hand_string
10 | right_hand_string
11 |
12 | transformer
13 | US2CompoundValueTransformer
14 | type
15 | String
16 |
17 | non_optionalCompoundString
18 |
19 | nonoptional
20 | true
21 | key
22 |
23 | non_optional_left_hand_string
24 | non_optional_right_hand_string
25 |
26 | transformer
27 | US2CompoundValueTransformer
28 | type
29 | String
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/TestObjectOne.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TestObjectOne.swift
3 | // US2Mapper
4 | //
5 | // Created by Anton Doudarev on 6/25/15.
6 | // Copyright © 2015 US2Mapper. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class _TestObjectOne {
12 | var optionalString : String?
13 |
14 | required init(_optionalString: Any?) {
15 | optionalString = typeCast(_optionalString)
16 | }
17 |
18 | convenience init?(_ dictionary: Dictionary) {
19 | let dynamicTypeString = "\(self.dynamicType)"
20 | let className = dynamicTypeString.componentsSeparatedByString(".").last
21 |
22 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled: true) {
23 | self.init(_optionalString: valuesDict["optionalString"]!)
24 | } else {
25 | self.init(_optionalString : nil)
26 | return nil
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/documentation/nested_mapping.md:
--------------------------------------------------------------------------------
1 | ##Example - Nested Mapping
2 |
3 | US2MapperKit supports nested mapping for added flexibility. When mapping against a Dictionary, **dot** notation can be used to reference values in the response. Observe the following response.
4 |
5 | **Response Dictionary**
6 |
7 | ```
8 | {
9 | "business_uuid" : 9223123456754776000,
10 | "business_name" : "UsTwoRestaurant",
11 | "business_ratings" : [ 5, 4, 5, 4 ],
12 | "business_location" : {
13 | "longitude" : 40.7053319,
14 | "latitude" : -74.0129945
15 | },
16 | "business_open" : 1
17 | }
18 | ```
19 |
20 | Although the location in the dictionary is formatted to be handled as custom Location object, assume the need to directly assign the longitude and latitude, as properties of a Business object.
21 |
22 | **Business.plist**
23 |
24 |
25 | 
26 |
27 |
28 | Using the **dot** notation per the example above one can map values as needed with ease.
29 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectTwo.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectTwo {
5 |
6 |
7 |
8 | required init() {
9 |
10 | }
11 |
12 | convenience init?(_ dictionary: Dictionary) {
13 |
14 | let dynamicTypeString = "\(self.dynamicType)"
15 | let className = dynamicTypeString.componentsSeparatedByString(".").last
16 |
17 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
18 |
19 |
20 | self.init()
21 |
22 | } else {
23 | self.init()
24 |
25 | return nil
26 | }
27 | }
28 |
29 | func updateWithDictionary(dictionary: Dictionary) {
30 |
31 | let dynamicTypeString = "\(self.dynamicType)"
32 | let className = dynamicTypeString.componentsSeparatedByString(".").last
33 |
34 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) { }
35 | }
36 | }
--------------------------------------------------------------------------------
/US2MapperKit/US2MapperKit/US2MapperKitOSX/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | com.ustwo.US2MapperKit
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSHumanReadableCopyright
24 | Copyright © 2015 ustwo. All rights reserved.
25 | NSPrincipalClass
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Test Case Objects/US2ExampleClosureTransformer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // US2ExampleClosureTransformer.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton on 9/3/15.
6 | // Copyright (c) 2015 ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | public class US2ExampleClosureTransformer : US2TransformerProtocol {
13 | public func transformValues(inputValues : Dictionary?) -> Any? {
14 | if let handlerType = inputValues!["handler_type"] as? String {
15 | if handlerType == "uppercase" {
16 |
17 | func returnCapitalizedString(value: String) -> String {
18 | return value.uppercaseString
19 | }
20 | return returnCapitalizedString
21 |
22 | } else if handlerType == "lowercase" {
23 | func returnLowercaseString(value: String) -> String {
24 | return value.lowercaseString
25 | }
26 | return returnLowercaseString
27 | }
28 | }
29 |
30 | return nil
31 | }
32 | }
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License (MIT)
3 | *
4 | * Copyright (c) 2015 ustwo studio inc (www.ustwo.com)
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
--------------------------------------------------------------------------------
/Source/US2MapperKit/Parsers/NativeValueArrayParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NativeValueArrayParser.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class NativeValueArrayParser {
12 |
13 | // MARK Maps Array representation of native values from a Dictionary of objects
14 |
15 | class func arrayRepresentation(collectionSubType : String?, data : Dictionary, instantiator : US2InstantiatorProtocol) -> [AnyObject] {
16 |
17 | var valueArray : [AnyObject] = []
18 |
19 | for (_, subDictValue) in data {
20 | valueArray.append(subDictValue)
21 | }
22 |
23 | return valueArray
24 | }
25 |
26 | // MARK Maps Array representation of native values from an Array of objects
27 |
28 | class func arrayRepresentation(collectionSubType : String?, data :[AnyObject], instantiator : US2InstantiatorProtocol) -> [AnyObject] {
29 |
30 | var valueArray : [AnyObject] = []
31 |
32 | for subDictValue in data {
33 | valueArray.append(subDictValue)
34 | }
35 |
36 | return valueArray
37 | }
38 | }
--------------------------------------------------------------------------------
/documentation/changelog.md:
--------------------------------------------------------------------------------
1 | #US2MapperKit ChangeLog
2 |
3 | ###Version 0.2.0
4 |
5 | #####Important Upgrade Notes
6 |
7 | Please note the following API/project changes have been made:
8 |
9 | * New method introduced to allow the developer to update instance values with a new a dictionary. A new method is generated as part of the internal model object `func updateWithDictionary(dictionary: Dictionary)`. You can now update values on an existing instance.
10 | * Fixes [Issue #21](https://github.com/ustwo/US2MapperKit/issues/21)
11 | * The `US2TransformerProtocol` has been updated with support for returning objects of `Any` type, which includes support for _Struct_, _Enums_, _Closures_, and _Tuples_.
12 | * Fixes [Issue #23](https://github.com/ustwo/US2MapperKit/issues/23)
13 |
14 | #####Important Upgrade Notes
15 |
16 | Be sure to update your custom transformers accordingly for continued support of custom transformers.
17 |
18 | ```
19 | Version 0.1.0 US2TransformerProtocol Definition
20 |
21 | public protocol US2TransformerProtocol {
22 | func transformValues(inputValues : Dictionary?) -> AnyObject?
23 | }
24 |
25 |
26 | Version 0.2.0 US2TransformerProtocol Definition
27 |
28 | public protocol US2TransformerProtocol {
29 | func transformValues(inputValues : Dictionary?) -> Any?
30 | }
31 |
32 | ```
33 |
34 | ###Version 0.1.0
35 |
36 | Initial Release
37 |
38 |
--------------------------------------------------------------------------------
/documentation/complex_value_types.md:
--------------------------------------------------------------------------------
1 | ##Example - Complex Value Types
2 | US2MapperKit's support for mapping complete types allows for creating object types as other objects generated. Let's assume in the example below that the business listing result returns a sub-dictionary for a location, and we would like to store it as a Location type.
3 |
4 | **Response Dictionary**
5 |
6 | ```
7 | {
8 | 'business_uuid' : 9223123456754775807,
9 | 'business_name' : 'UsTwo Restaurant',
10 | 'business_rating' : 5,
11 | 'business_location :
12 | {
13 | 'longitude' : 40.7053319,
14 | 'latitude' : -74.0129945
15 | },
16 | 'business_open' : 1
17 | }
18 |
19 | ```
20 |
21 | First, create a model mapping for the Location object.
22 |
23 | **Location.plist**
24 |
25 |
26 | 
27 |
28 |
29 | Once the model mapping for a location has generated a `Location` object, and it has been added to the project, update the Business object mapping by defining a location property typed as **Location**
30 |
31 | **Business.plist**
32 |
33 |
34 | 
35 |
36 |
37 |
38 | When parsing the data for a `Business` object, US2MapperKit will create a `Location` instance, and will assign the resulting value to the location property of the `Business` instance before returning it :)
39 |
--------------------------------------------------------------------------------
/Source/US2MapperKit/Parsers/NativeValueDictionaryParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NativeValueDictionaryParser.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class NativeValueDictionaryParser {
12 |
13 | // MARK Maps Dictionary representation of native values from an Array of objects
14 |
15 | class func dictionaryRepresentation(collectionSubType : String?, data : Dictionary, instantiator : US2InstantiatorProtocol) -> Dictionary {
16 |
17 | var valueDictionary = Dictionary()
18 | var intKey = 0
19 |
20 | for (key, subDictValue) in data {
21 | valueDictionary[String(key)] = subDictValue
22 | intKey++
23 | }
24 |
25 | return valueDictionary
26 | }
27 |
28 | // MARK Maps Dictionary representation of native values from an Array of objects
29 |
30 | class func dictionaryRepresentation(collectionSubType : String?, data : [AnyObject], instantiator : US2InstantiatorProtocol) -> Dictionary {
31 |
32 | var valueDictionary = Dictionary()
33 | var intKey = 0
34 |
35 | for subDictValue in data {
36 | valueDictionary[String(intKey)] = subDictValue
37 | intKey++
38 | }
39 |
40 | return valueDictionary
41 | }
42 | }
--------------------------------------------------------------------------------
/documentation/non_optional_value_types.md:
--------------------------------------------------------------------------------
1 | ##Example - Non Optional Value Types
2 | If a property is non-optional, such as the **uuid** property for the Business model object, a **nonoptional** can be added to the property definition in the model mapping. Let's take a quick peak at the `Business.plist`.
3 |
4 | **Business.plist**
5 |
6 |
7 | 
8 |
9 |
10 | Once the model mapping has been updated, perform a build **(⌘-B)**, and the changes should be reflected accordingly in the internal `_Business.swift` class.
11 |
12 | **Business.swift**
13 |
14 |
15 | ```
16 | import Foundation
17 | import US2MapperKit
18 |
19 | class _Business {
20 |
21 | var rating : Int?
22 | var longitude : Float?
23 | var latitude : Float?
24 | var open : Bool?
25 | var name : String?
26 |
27 | var uuid : Double
28 |
29 | required init(_uuid : Double) {...}
30 |
31 | convenience init?(_ dictionary: Dictionary) {...}
32 | }
33 | ```
34 |
35 | Once the script has updated the internal file, the uuid property should be a non-optional property, and been added to the required initializer as an input parameter. In the case that the response dictionary does not contain a value for the uuid, the fail-able initializer will return nil.
36 |
37 | ###Default Values
38 | To assign a default value definition for a non-optional property, follow the example found in the [Defining Default Values](/documentation/default_values.md) section of the documentation
39 |
--------------------------------------------------------------------------------
/Source/US2MapperKit/Parsers/ComplexValueArrayParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ComplexValueArrayParser.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class ComplexValueArrayParser {
12 |
13 | // MARK Maps array representation of complex objects from an Array of Dictionary objects
14 |
15 | class func arrayRepresentation(collectionSubType : String?, data : [Dictionary], instantiator : US2InstantiatorProtocol) -> [AnyObject] {
16 |
17 | var valueArray : [AnyObject] = []
18 |
19 | for subArrayValue in data {
20 | if let complexTypeValue: AnyObject = instantiator.newInstance(ofType: collectionSubType!, withValue: subArrayValue) {
21 | valueArray.append(complexTypeValue)
22 | }
23 | }
24 | return valueArray
25 | }
26 |
27 | // MARK array representation of complex objects from a Dictionary of Dictionary objects
28 |
29 | class func arrayRepresentation(collectionSubType : String?, data : Dictionary>, instantiator : US2InstantiatorProtocol) -> [AnyObject] {
30 |
31 | var valueArray : [AnyObject] = []
32 |
33 | for (_, subDictValue) in data {
34 | if let complexTypeValue: AnyObject = instantiator.newInstance(ofType: collectionSubType!, withValue: subDictValue) {
35 | valueArray.append(complexTypeValue)
36 | }
37 | }
38 | return valueArray
39 | }
40 | }
--------------------------------------------------------------------------------
/documentation/collection_types.md:
--------------------------------------------------------------------------------
1 | ##Example - Collection Types
2 | US2MapperKit's support for mapping Dictionaries and Arrays when parsing a responses' collection values is quite easy. Let's assume in the example below that the business listing result returns an array of ratings, and we would like to store them as an Array type
3 |
4 | **Response Dictionary**
5 |
6 | ```
7 | {
8 | "business_uuid" : 9223123456754776000,
9 | "business_name" : "UsTwoRestaurant",
10 | "business_ratings" : [ 5, 4, 5, 4 ],
11 | "business_location" : {
12 | "longitude" : 40.7053319,
13 | "latitude" : -74.0129945
14 | },
15 | "business_open" : 1
16 | }
17 | ```
18 | First, update a model mapping for the Business object by defining setting the **type** key definition to `Array`, and adding a new **collection_subtype** key to define the subtype as `Int`.
19 |
20 | **Business.plist**
21 |
22 |
23 | 
24 |
25 |
26 | When parsing the data for a `Business` object, US2MapperKit will create a parsed ratings `Array`, and will assign the resulting value to the ratings property of the `Business` instance before returning it.
27 |
28 | This also works for Dictionaries by setting the **type** key to Dictionary. When parsing a dictionary, US2MapperKit will use the assigned keys in the response when setting the values in the parsed `Dictionary`. If the response is an array, and the property to be mapped is a dictionary, US2MappkerKit will use an incremental index as the key starting with zero.
29 |
30 | Note: When parsing collections, **collection_subtype** can be any of the native value types `String`, `Int`, `Double`, `Float`, `Bool`, and/or any object generated by a US2MapperKit.
31 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectThirteen.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalStruct
6 |
7 | type
8 | StructExample
9 | transformer
10 | US2ExampleStructTransformer
11 | key
12 |
13 | string1
14 | string2
15 |
16 |
17 | optionalEnum
18 |
19 | type
20 | EnumExample
21 | transformer
22 | US2ExampleEnumTransformer
23 | key
24 |
25 | enumValue
26 |
27 |
28 | optionalTuple
29 |
30 | type
31 | (val1 : Double, val2 : Double)
32 | transformer
33 | US2ExampleTupleTransformer
34 | key
35 |
36 | value_one
37 | value_two
38 |
39 |
40 | optionalUppercaseCompletionHandler
41 |
42 | type
43 | ((value : String) -> String)
44 | transformer
45 | US2ExampleClosureTransformer
46 | key
47 |
48 | handler_type
49 |
50 |
51 | optionalLowercaseCompletionHandler
52 |
53 | type
54 | ((value : String) -> String)
55 | transformer
56 | US2ExampleClosureTransformer
57 | key
58 |
59 | handler_type
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectFive.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectFive {
5 |
6 | var optionalSubType : TestObjectThree?
7 |
8 | var non_optionalSubType : TestObjectThree
9 |
10 | required init(_non_optionalSubType : TestObjectThree) {
11 |
12 | non_optionalSubType = _non_optionalSubType
13 | }
14 |
15 | convenience init?(_ dictionary: Dictionary) {
16 |
17 | let dynamicTypeString = "\(self.dynamicType)"
18 | let className = dynamicTypeString.componentsSeparatedByString(".").last
19 |
20 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
21 |
22 | let temp_non_optionalSubType : TestObjectThree = typeCast(valuesDict["non_optionalSubType"])!
23 |
24 | self.init(_non_optionalSubType : temp_non_optionalSubType)
25 |
26 | if let unwrapped_optionalSubType : Any = valuesDict["optionalSubType"] {
27 | optionalSubType = typeCast(unwrapped_optionalSubType)
28 | }
29 |
30 | } else {
31 | self.init(_non_optionalSubType : TestObjectThree(Dictionary())!)
32 |
33 | return nil
34 | }
35 | }
36 |
37 | func updateWithDictionary(dictionary: Dictionary) {
38 |
39 | let dynamicTypeString = "\(self.dynamicType)"
40 | let className = dynamicTypeString.componentsSeparatedByString(".").last
41 |
42 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
43 | if let unwrapped_optionalSubType : Any = valuesDict["optionalSubType"] {
44 | optionalSubType = typeCast(unwrapped_optionalSubType)
45 | }
46 |
47 | if let unwrapped_non_optionalSubType : Any = valuesDict["non_optionalSubType"] {
48 | non_optionalSubType = typeCast(unwrapped_non_optionalSubType)!
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectSeven.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectSeven {
5 |
6 | var optionalArrayType : [TestObjectFour]?
7 |
8 | var non_optionalArrayType : [TestObjectFour]
9 |
10 | required init(_non_optionalArrayType : [TestObjectFour]) {
11 |
12 | non_optionalArrayType = _non_optionalArrayType
13 | }
14 |
15 | convenience init?(_ dictionary: Dictionary) {
16 |
17 | let dynamicTypeString = "\(self.dynamicType)"
18 | let className = dynamicTypeString.componentsSeparatedByString(".").last
19 |
20 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
21 |
22 | let temp_non_optionalArrayType : [TestObjectFour] = typeCast(valuesDict["non_optionalArrayType"])!
23 |
24 | self.init(_non_optionalArrayType : temp_non_optionalArrayType)
25 |
26 | if let unwrapped_optionalArrayType : Any = valuesDict["optionalArrayType"] {
27 | optionalArrayType = typeCast(unwrapped_optionalArrayType)
28 | }
29 |
30 | } else {
31 | self.init(_non_optionalArrayType : [TestObjectFour]())
32 |
33 | return nil
34 | }
35 | }
36 |
37 | func updateWithDictionary(dictionary: Dictionary) {
38 |
39 | let dynamicTypeString = "\(self.dynamicType)"
40 | let className = dynamicTypeString.componentsSeparatedByString(".").last
41 |
42 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
43 | if let unwrapped_optionalArrayType : Any = valuesDict["optionalArrayType"] {
44 | optionalArrayType = typeCast(unwrapped_optionalArrayType)
45 | }
46 |
47 | if let unwrapped_non_optionalArrayType : Any = valuesDict["non_optionalArrayType"] {
48 | non_optionalArrayType = typeCast(unwrapped_non_optionalArrayType)!
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectSix.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectSix {
5 |
6 | var optionalCompoundString : String?
7 |
8 | var non_optionalCompoundString : String
9 |
10 | required init(_non_optionalCompoundString : String) {
11 |
12 | non_optionalCompoundString = _non_optionalCompoundString
13 | }
14 |
15 | convenience init?(_ dictionary: Dictionary) {
16 |
17 | let dynamicTypeString = "\(self.dynamicType)"
18 | let className = dynamicTypeString.componentsSeparatedByString(".").last
19 |
20 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
21 |
22 | let temp_non_optionalCompoundString : String = typeCast(valuesDict["non_optionalCompoundString"])!
23 |
24 | self.init(_non_optionalCompoundString : temp_non_optionalCompoundString)
25 |
26 | if let unwrapped_optionalCompoundString : Any = valuesDict["optionalCompoundString"] {
27 | optionalCompoundString = typeCast(unwrapped_optionalCompoundString)
28 | }
29 |
30 | } else {
31 | self.init(_non_optionalCompoundString : String())
32 |
33 | return nil
34 | }
35 | }
36 |
37 | func updateWithDictionary(dictionary: Dictionary) {
38 |
39 | let dynamicTypeString = "\(self.dynamicType)"
40 | let className = dynamicTypeString.componentsSeparatedByString(".").last
41 |
42 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
43 | if let unwrapped_optionalCompoundString : Any = valuesDict["optionalCompoundString"] {
44 | optionalCompoundString = typeCast(unwrapped_optionalCompoundString)
45 | }
46 |
47 | if let unwrapped_non_optionalCompoundString : Any = valuesDict["non_optionalCompoundString"] {
48 | non_optionalCompoundString = typeCast(unwrapped_non_optionalCompoundString)!
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectEight.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectEight {
5 |
6 | var optionalDictionaryType : Dictionary?
7 |
8 | var non_optionalDictionaryType : Dictionary
9 |
10 | required init(_non_optionalDictionaryType : Dictionary) {
11 |
12 | non_optionalDictionaryType = _non_optionalDictionaryType
13 | }
14 |
15 | convenience init?(_ dictionary: Dictionary) {
16 |
17 | let dynamicTypeString = "\(self.dynamicType)"
18 | let className = dynamicTypeString.componentsSeparatedByString(".").last
19 |
20 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
21 |
22 | let temp_non_optionalDictionaryType : Dictionary = typeCast(valuesDict["non_optionalDictionaryType"])!
23 |
24 | self.init(_non_optionalDictionaryType : temp_non_optionalDictionaryType)
25 |
26 | if let unwrapped_optionalDictionaryType : Any = valuesDict["optionalDictionaryType"] {
27 | optionalDictionaryType = typeCast(unwrapped_optionalDictionaryType)
28 | }
29 |
30 | } else {
31 | self.init(_non_optionalDictionaryType : Dictionary())
32 |
33 | return nil
34 | }
35 | }
36 |
37 | func updateWithDictionary(dictionary: Dictionary) {
38 |
39 | let dynamicTypeString = "\(self.dynamicType)"
40 | let className = dynamicTypeString.componentsSeparatedByString(".").last
41 |
42 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
43 | if let unwrapped_non_optionalDictionaryType : Any = valuesDict["non_optionalDictionaryType"] {
44 | non_optionalDictionaryType = typeCast(unwrapped_non_optionalDictionaryType)!
45 | }
46 |
47 | if let unwrapped_optionalDictionaryType : Any = valuesDict["optionalDictionaryType"] {
48 | optionalDictionaryType = typeCast(unwrapped_optionalDictionaryType)
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/Source/US2MapperKit/Transformer/Transformer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Transformer.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | var transformerInstances : Dictionary = Dictionary ()
12 |
13 | final class Transformer : Parser {
14 |
15 | class func transformedValue(from data : Dictionary, applying propertyMapping : Dictionary, employing instantiator : US2InstantiatorProtocol) -> Any? {
16 |
17 | if let transformClass = propertyMapping[US2MapperTransformerKey] as? String {
18 | if let jsonKeys = propertyMapping[US2MapperJSONKey] as? [String] {
19 | if let transformedValue: Any = transformedValueRepresentation(transformClass, jsonKeys : jsonKeys, data: data, instantiator: instantiator) {
20 | return transformedValue
21 | }
22 | }
23 | }
24 | return nil
25 | }
26 |
27 | class func transformedValueRepresentation(mapperClass : String, jsonKeys : [String], data : Dictionary, instantiator : US2InstantiatorProtocol) -> Any? {
28 |
29 | var valueDictionary : Dictionary = Dictionary()
30 |
31 | for jsonKey in jsonKeys {
32 | if let jsonValue: AnyObject = dictionaryValueForKey(jsonKey, dictionary: data) {
33 | valueDictionary[jsonKey] = jsonValue
34 | }
35 | }
36 |
37 | if let customTransformer = customTransformer(mapperClass, instantiator: instantiator) {
38 | if let transformedValue: Any = customTransformer.transformValues(valueDictionary) {
39 | return transformedValue;
40 | }
41 | }
42 |
43 | return nil
44 | }
45 |
46 |
47 | class func customTransformer(className : String, instantiator : US2InstantiatorProtocol) -> US2TransformerProtocol? {
48 | if let transformer = transformerInstances[className] {
49 | return transformer
50 | } else {
51 | if let transformer = instantiator.transformerFromString(className) {
52 | transformerInstances[className] = transformer
53 | return transformer
54 | } else {
55 | return nil
56 | }
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectFour.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalInt
6 |
7 | key
8 | optional_int
9 | type
10 | Int
11 |
12 | optionalString
13 |
14 | key
15 | optional_string
16 | type
17 | String
18 |
19 | optionalDouble
20 |
21 | key
22 | optional_double
23 | type
24 | Double
25 |
26 | optionalFloat
27 |
28 | key
29 | optional_float
30 | type
31 | Float
32 |
33 | optionalBool
34 |
35 | key
36 | optional_bool
37 | type
38 | Bool
39 |
40 | non_optionalInt
41 |
42 | nonoptional
43 | true
44 | default
45 | 500
46 | key
47 | non_optional_int
48 | type
49 | Int
50 |
51 | non_optionalString
52 |
53 | nonoptional
54 | true
55 | default
56 | Non-Optional Hello
57 | key
58 | non_optional_string
59 | type
60 | String
61 |
62 | non_optionalDouble
63 |
64 | nonoptional
65 | true
66 | default
67 | 50.0
68 | key
69 | non_optional_double
70 | type
71 | Double
72 |
73 | non_optionalFloat
74 |
75 | nonoptional
76 | true
77 | default
78 | 60.0
79 | key
80 | non_optional_float
81 | type
82 | Float
83 |
84 | non_optionalBool
85 |
86 | nonoptional
87 | true
88 | default
89 | true
90 | key
91 | non_optional_bool
92 | type
93 | Bool
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectNine.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalArrayStringType
6 |
7 | key
8 | optional_array_string_type
9 | type
10 | Array
11 | collection_subtype
12 | String
13 |
14 | optionalArrayDoubleType
15 |
16 | key
17 | optional_array_double_type
18 | type
19 | Array
20 | collection_subtype
21 | Double
22 |
23 | optionalArrayFloatType
24 |
25 | key
26 | optional_array_float_type
27 | type
28 | Array
29 | collection_subtype
30 | Float
31 |
32 | optionalArrayIntType
33 |
34 | key
35 | optional_array_int_type
36 | type
37 | Array
38 | collection_subtype
39 | Int
40 |
41 | non_optionalArrayStringType
42 |
43 | nonoptional
44 | true
45 | key
46 | non_optional_array_string_type
47 | type
48 | Array
49 | collection_subtype
50 | String
51 |
52 | non_optionalArrayDoubleType
53 |
54 | nonoptional
55 | true
56 | key
57 | non_optional_array_double_type
58 | type
59 | Array
60 | collection_subtype
61 | Double
62 |
63 | non_optionalArrayFloatType
64 |
65 | nonoptional
66 | true
67 | key
68 | non_optional_array_float_type
69 | type
70 | Array
71 | collection_subtype
72 | Float
73 |
74 | non_optionalArrayIntType
75 |
76 | nonoptional
77 | true
78 | key
79 | non_optional_array_int_type
80 | type
81 | Array
82 | collection_subtype
83 | Int
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/Source/US2MapperKit/Parsers/NativeTypeParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NativeTypeParser.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class NativeTypeParser {
12 |
13 | class func nativeRepresentation(fromValue data : AnyObject, asType objectType : String?) -> AnyObject? {
14 | return convertValue(data, dataType : objectType!)
15 | }
16 |
17 | class func convertValue(value : AnyObject, dataType : String) -> AnyObject? {
18 | switch dataType {
19 | case US2DataTypeString:
20 | if value is NSNumber {
21 | return numericString(value as! NSNumber)
22 | }
23 | return "\(value)"
24 | case US2DataTypeDouble:
25 | return Double(value.doubleValue)
26 | case US2DataTypeFloat:
27 | return Float(value.floatValue)
28 | case US2DataTypeInt:
29 | return Int(value.integerValue)
30 | case US2DataTypeBool:
31 | return value.boolValue
32 | default:
33 | return value
34 | }
35 | }
36 |
37 | class func numericString(value: NSNumber) -> String {
38 | switch CFNumberGetType(value){
39 | case .SInt8Type:
40 | return String(value.charValue)
41 | case .SInt16Type:
42 | return String(value.shortValue)
43 | case .SInt32Type:
44 | return String(value.intValue)
45 | case .SInt64Type:
46 | return String(value.longLongValue)
47 | case .Float32Type:
48 | return String(stringInterpolationSegment: value.floatValue)
49 | case .Float64Type:
50 | return String(stringInterpolationSegment: value.doubleValue)
51 | case .CharType:
52 | return String(value.charValue)
53 | case .ShortType:
54 | return String(value.shortValue)
55 | case .IntType:
56 | return String(value.integerValue)
57 | case .LongType:
58 | return String(value.longValue)
59 | case .LongLongType:
60 | return String(value.longLongValue)
61 | case .FloatType:
62 | return String(stringInterpolationSegment: value.floatValue)
63 | case .DoubleType:
64 | return String(stringInterpolationSegment: value.doubleValue)
65 | default:
66 | return String(stringInterpolationSegment: value.doubleValue)
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Source/US2MapperKit/Parsers/ComplexValueDictionaryParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ComplexValueDictionaryParser.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class ComplexValueDictionaryParser {
12 |
13 | // MARK Maps dictionary representation of complex objects from a Dictionary of Dictionary objects
14 |
15 | class func dictionaryRepresentation(collectionSubType : String?, data : Dictionary>, instantiator : US2InstantiatorProtocol) -> Dictionary {
16 |
17 | var valueDictionary : Dictionary = Dictionary()
18 |
19 | for (key, subDictValue) in data {
20 | if let complexTypeValue: AnyObject = instantiator.newInstance(ofType: collectionSubType!, withValue: subDictValue) {
21 | valueDictionary["\(key)"] = complexTypeValue
22 | }
23 | }
24 | return valueDictionary
25 | }
26 |
27 | // MARK Maps dictionary representation of complex objects from an Array of Dictionary objects
28 |
29 | class func dictionaryRepresentation(collectionSubType : String?, data : [Dictionary], instantiator : US2InstantiatorProtocol) -> Dictionary {
30 |
31 | var valueDictionary : Dictionary = Dictionary()
32 | var intKey = 0
33 | for subDictValue in data {
34 | if let complexTypeValue: AnyObject = instantiator.newInstance(ofType: collectionSubType!, withValue: subDictValue) {
35 | valueDictionary["\(intKey)"] = complexTypeValue
36 | intKey++
37 | }
38 | }
39 | return valueDictionary
40 | }
41 |
42 | // MARK Maps dictionary representation of complex objects from a single dictionary instance returned
43 |
44 | class func dictionaryRepresentation(collectionSubType : String?, data : Dictionary, instantiator : US2InstantiatorProtocol) -> Dictionary {
45 |
46 | var valueDictionary : Dictionary = Dictionary()
47 |
48 | if let complexTypeValue: AnyObject = instantiator.newInstance(ofType: collectionSubType!, withValue: data) {
49 | valueDictionary["0"] = complexTypeValue
50 | }
51 |
52 | return valueDictionary
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectTwelve.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalInt
6 |
7 | key
8 | top_level_key.optional_int
9 | type
10 | Int
11 |
12 | optionalString
13 |
14 | key
15 | top_level_key.optional_string
16 | type
17 | String
18 |
19 | optionalDouble
20 |
21 | key
22 | top_level_key,optional_double
23 | type
24 | Double
25 |
26 | optionalFloat
27 |
28 | key
29 | top_level_key.optional_float
30 | type
31 | Float
32 |
33 | optionalBool
34 |
35 | key
36 | top_level_key.optional_bool
37 | type
38 | Bool
39 |
40 | non_optionalInt
41 |
42 | nonoptional
43 | true
44 | default
45 | 500
46 | key
47 | non_optional_int
48 | type
49 | Int
50 |
51 | non_optionalString
52 |
53 | nonoptional
54 | true
55 | default
56 | Non-Optional Hello
57 | key
58 | non_optional_string
59 | type
60 | String
61 |
62 | non_optionalDouble
63 |
64 | nonoptional
65 | true
66 | default
67 | 50.0
68 | key
69 | top_level_key.non_optional_double
70 | type
71 | Double
72 |
73 | non_optionalFloat
74 |
75 | nonoptional
76 | true
77 | default
78 | 60.0
79 | key
80 | top_level_key.non_optional_float
81 | type
82 | Float
83 |
84 | non_optionalBool
85 |
86 | nonoptional
87 | true
88 | default
89 | true
90 | key
91 | top_level_key.non_optional_bool
92 | type
93 | Bool
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectTen.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalDictionaryStringType
6 |
7 | key
8 | optional_dictionary_string_type
9 | type
10 | Dictionary
11 | collection_subtype
12 | String
13 |
14 | optionalDictionaryDoubleType
15 |
16 | key
17 | optional_dictionary_double_type
18 | type
19 | Dictionary
20 | collection_subtype
21 | Double
22 |
23 | optionalDictionaryFloatType
24 |
25 | key
26 | optional_dictionary_float_type
27 | type
28 | Dictionary
29 | collection_subtype
30 | Float
31 |
32 | optionalDictionaryIntType
33 |
34 | key
35 | optional_dictionary_int_type
36 | type
37 | Dictionary
38 | collection_subtype
39 | Int
40 |
41 | non_optionalDictionaryStringType
42 |
43 | nonoptional
44 | true
45 | key
46 | non_optional_dictionary_string_type
47 | type
48 | Dictionary
49 | collection_subtype
50 | String
51 |
52 | non_optionalDictionaryDoubleType
53 |
54 | nonoptional
55 | true
56 | key
57 | non_optional_dictionary_double_type
58 | type
59 | Dictionary
60 | collection_subtype
61 | Double
62 |
63 | non_optionalDictionaryFloatType
64 |
65 | nonoptional
66 | true
67 | key
68 | non_optional_dictionary_float_type
69 | type
70 | Dictionary
71 | collection_subtype
72 | Float
73 |
74 | non_optionalDictionaryIntType
75 |
76 | nonoptional
77 | true
78 | key
79 | non_optional_dictionary_int_type
80 | type
81 | Dictionary
82 | collection_subtype
83 | Int
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectEleven.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalInt
6 |
7 | key
8 | top_level_key.optional_int
9 | type
10 | Int
11 |
12 | optionalString
13 |
14 | key
15 | top_level_key.optional_string
16 | type
17 | String
18 |
19 | optionalDouble
20 |
21 | key
22 | top_level_key,optional_double
23 | type
24 | Double
25 |
26 | optionalFloat
27 |
28 | key
29 | top_level_key.optional_float
30 | type
31 | Float
32 |
33 | optionalBool
34 |
35 | key
36 | top_level_key.optional_bool
37 | type
38 | Bool
39 |
40 | non_optionalInt
41 |
42 | nonoptional
43 | true
44 | default
45 | 500
46 | key
47 | top_level_key.non_optional_int
48 | type
49 | Int
50 |
51 | non_optionalString
52 |
53 | nonoptional
54 | true
55 | default
56 | Non-Optional Hello
57 | key
58 | top_level_key.non_optional_string
59 | type
60 | String
61 |
62 | non_optionalDouble
63 |
64 | nonoptional
65 | true
66 | default
67 | 50.0
68 | key
69 | top_level_key.non_optional_double
70 | type
71 | Double
72 |
73 | non_optionalFloat
74 |
75 | nonoptional
76 | true
77 | default
78 | 60.0
79 | key
80 | top_level_key.non_optional_float
81 | type
82 | Float
83 |
84 | non_optionalBool
85 |
86 | nonoptional
87 | true
88 | default
89 | true
90 | key
91 | top_level_key.non_optional_bool
92 | type
93 | Bool
94 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/Source/US2MapperKit/Validator/Validator.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Validator.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public class Validator {
12 |
13 | // MARK Validates that all the non-optional values were received or defaulted
14 |
15 | final class func validateResponse(forValues retrievedValues : Dictionary,
16 | mappedTo mappingConfiguration : Dictionary>,
17 | forType className : String,
18 | withData data : Dictionary) -> Bool {
19 |
20 | #if US2MAPPER_DEBUG
21 | var missingPropertyKeyArray = Array()
22 | #endif
23 |
24 | // Validate that all non-optional properties have a value assigned
25 |
26 | for (propertyKey, propertyMapping) in mappingConfiguration {
27 | if let isPropertyNonOptional : AnyObject = propertyMapping[US2MapperNonOptionalKey] {
28 | if isPropertyNonOptional.boolValue == true {
29 | if let _ = retrievedValues[propertyKey] {
30 | // If value was mapped, continue with validation
31 | continue
32 | } else {
33 | #if US2MAPPER_DEBUG
34 | missingPropertyKeyArray.append(propertyKey)
35 | #else
36 | return false
37 | #endif
38 | }
39 | }
40 | }
41 | }
42 |
43 | #if US2MAPPER_DEBUG
44 | if (missingPropertyKeyArray.count > 0) {
45 | printDebugStatement(className, missingPropertyKeyArray: missingPropertyKeyArray, data : data)
46 | return false
47 | }
48 | #endif
49 |
50 | return true
51 | }
52 |
53 | // MARK Debug Enabled Methods
54 |
55 | final class func printDebugStatement(className : String, missingPropertyKeyArray : Array, data : Dictionary){
56 | if (missingPropertyKeyArray.count > 0) {
57 | print("\n\n\(className) instance could not be parsed, missing values for the following non-optional properties:")
58 | for propertyKey in missingPropertyKeyArray {
59 | print("\n- \(propertyKey)")
60 | }
61 |
62 | print("\n\nResponse:\n\(data)\n\n")
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/documentation/custom_transforms_tuples.md:
--------------------------------------------------------------------------------
1 | ##Example - Tuple Transformations
2 |
3 | As of version 0.2.0 of U2MapperKit, the ability to map tuples via the `US2TransformerProtocol` as support was added. This ensures that we can return an a value of `Any` type. Let's look at a dictionary for a business object, and see how we can map a the coordinates as a tuple.
4 |
5 | **Response Dictionary**
6 |
7 | ```
8 | {
9 | 'business_uuid' : 9223123456754775807,
10 | 'business_name' : 'UsTwo Restaurant',
11 | 'business_longitude' : 40.7053319,
12 | 'business_latitude' : -74.0129945,
13 | }
14 | ```
15 |
16 | For the purposes of the example, let's create a mapper that returns a tuple. First, create an enum to represent the business type for our custom Business Object:
17 |
18 |
19 | **US2TupleCoordinateExampleTransformer Implementation**
20 |
21 | ```
22 | let longitudeKey = "business_longitude"
23 | let latitudeKey = "business_latitude"
24 |
25 | public class US2TupleCoordinateExampleTransformer : US2TransformerProtocol {
26 |
27 | public func transformValues(inputValues : Dictionary?) -> Any? {
28 | if let coordinateDictionary = inputValues as? Dictionary {
29 | if let unwrappedLongitude = coordinateDictionary[longitudeKey] as? Double {
30 | if let unwrappedLatitude = coordinateDictionary[latitudeKey] as? Double {
31 | return (longitude : unwrappedLongitude, latitude : unwrappedLatitude)
32 | }
33 | }
34 | }
35 | return nil
36 | }
37 | }
38 | ```
39 |
40 | Now that we have created a transformer, let's create mapping for our business Object:
41 |
42 | **Business.plist**
43 |
44 |
45 | 
46 |
47 |
48 | After the creation of the mapping, perform a build **(⌘-B)**. The changes should be reflected accordingly in the internal `_Business.swift` class.
49 |
50 |
51 | ```
52 | import Foundation
53 | import US2MapperKit
54 |
55 | class _Business {
56 | var uuid : Double?
57 | var name : String?
58 | var coordinates : (longitude : Double, latitude : Double)?
59 |
60 | required init() {...}
61 |
62 | convenience init?(_ dictionary: Dictionary) {...}
63 | }
64 | ```
65 |
66 | After calling the fail-able initializer - or udpateWithDictionary method with a dictioanry representation - US2MapperKit will use the custom transformer to map the tuple accordingly.
67 |
68 | Note: The the keys defined in the property mapping correspond to the keys in the dictionary of values passed to the ` public func transformValues(inputValues : Dictionary?) -> Any?` method defined by the protocol.
69 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Mapping/TestObjectThree.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | optionalString
6 |
7 | default
8 | Hello
9 | key
10 | optional_string
11 | type
12 | String
13 |
14 | optionalInt
15 |
16 | default
17 | 10
18 | key
19 | optional_int
20 | type
21 | Int
22 |
23 | optionalDouble
24 |
25 | default
26 | 20.0
27 | key
28 | optional_double
29 | type
30 | Double
31 |
32 | optionalFloat
33 |
34 | default
35 | 30.0
36 | key
37 | optional_float
38 | type
39 | Float
40 |
41 | optionalBool
42 |
43 | default
44 | true
45 | key
46 | optional_bool
47 | type
48 | Bool
49 |
50 | non_optionalString
51 |
52 | nonoptional
53 | true
54 | default
55 | Non-Optional Hello
56 | key
57 | non_optional_string
58 | type
59 | String
60 |
61 | non_optionalInt
62 |
63 | nonoptional
64 | true
65 | default
66 | 40
67 | key
68 | non_optional_int
69 | type
70 | Int
71 |
72 | non_optionalDouble
73 |
74 | nonoptional
75 | true
76 | default
77 | 50.0
78 | key
79 | non_optional_double
80 | type
81 | Double
82 |
83 | non_optionalFloat
84 |
85 | nonoptional
86 | true
87 | default
88 | 60.0
89 | key
90 | non_optional_float
91 | type
92 | Float
93 |
94 | non_optionalBool
95 |
96 | nonoptional
97 | true
98 | default
99 | false
100 | key
101 | non_optional_bool
102 | type
103 | Bool
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectThirteen.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectThirteen {
5 |
6 | var optionalStruct : StructExample?
7 | var optionalTuple : (val1 : Double, val2 : Double)?
8 | var optionalUppercaseCompletionHandler : ((value : String) -> String)?
9 | var optionalLowercaseCompletionHandler : ((value : String) -> String)?
10 | var optionalEnum : EnumExample?
11 |
12 |
13 | required init() {
14 |
15 | }
16 |
17 | convenience init?(_ dictionary: Dictionary) {
18 |
19 | let dynamicTypeString = "\(self.dynamicType)"
20 | let className = dynamicTypeString.componentsSeparatedByString(".").last
21 |
22 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
23 |
24 |
25 | self.init()
26 |
27 | if let unwrapped_optionalStruct : Any = valuesDict["optionalStruct"] {
28 | optionalStruct = typeCast(unwrapped_optionalStruct)
29 | }
30 |
31 | if let unwrapped_optionalTuple : Any = valuesDict["optionalTuple"] {
32 | optionalTuple = typeCast(unwrapped_optionalTuple)
33 | }
34 |
35 | if let unwrapped_optionalUppercaseCompletionHandler : Any = valuesDict["optionalUppercaseCompletionHandler"] {
36 | optionalUppercaseCompletionHandler = typeCast(unwrapped_optionalUppercaseCompletionHandler)
37 | }
38 |
39 | if let unwrapped_optionalLowercaseCompletionHandler : Any = valuesDict["optionalLowercaseCompletionHandler"] {
40 | optionalLowercaseCompletionHandler = typeCast(unwrapped_optionalLowercaseCompletionHandler)
41 | }
42 |
43 | if let unwrapped_optionalEnum : Any = valuesDict["optionalEnum"] {
44 | optionalEnum = typeCast(unwrapped_optionalEnum)
45 | }
46 |
47 | } else {
48 | self.init()
49 |
50 | return nil
51 | }
52 | }
53 |
54 | func updateWithDictionary(dictionary: Dictionary) {
55 |
56 | let dynamicTypeString = "\(self.dynamicType)"
57 | let className = dynamicTypeString.componentsSeparatedByString(".").last
58 |
59 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
60 | if let unwrapped_optionalStruct : Any = valuesDict["optionalStruct"] {
61 | optionalStruct = typeCast(unwrapped_optionalStruct)
62 | }
63 |
64 | if let unwrapped_optionalTuple : Any = valuesDict["optionalTuple"] {
65 | optionalTuple = typeCast(unwrapped_optionalTuple)
66 | }
67 |
68 | if let unwrapped_optionalUppercaseCompletionHandler : Any = valuesDict["optionalUppercaseCompletionHandler"] {
69 | optionalUppercaseCompletionHandler = typeCast(unwrapped_optionalUppercaseCompletionHandler)
70 | }
71 |
72 | if let unwrapped_optionalLowercaseCompletionHandler : Any = valuesDict["optionalLowercaseCompletionHandler"] {
73 | optionalLowercaseCompletionHandler = typeCast(unwrapped_optionalLowercaseCompletionHandler)
74 | }
75 |
76 | if let unwrapped_optionalEnum : Any = valuesDict["optionalEnum"] {
77 | optionalEnum = typeCast(unwrapped_optionalEnum)
78 | }
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/documentation/custom_transforms_struct.md:
--------------------------------------------------------------------------------
1 | ##Example - Struct Transformations
2 |
3 | As of version 0.2.0 of U2MapperKit, the ability to map structs via the `US2TransformerProtocol` as support was added. This ensures that we can return a value of `Any` type. Let's look at a dictionary for a business object and see how we can map a struct for the coordinates:
4 |
5 | **Response Dictionary**
6 |
7 | ```
8 | {
9 | 'business_uuid' : 9223123456754775807,
10 | 'business_name' : 'UsTwo Restaurant',
11 | 'business_longitude' : 40.7053319,
12 | 'business_latitude' : -74.0129945,
13 | }
14 | ```
15 |
16 | Unlike the model objects, US2MapperKit does not autogenerate structs, due to the lack of inheritance. Structs would be uncustomizable if it did, and would prevent the developer from using the many features Swift offers with structs. For the purposes of this example, let assume that we created a struct to represent the coordinates for our custom Business Object.
17 |
18 | **Struct Definition**
19 |
20 | ```
21 | struct Coordinate {
22 | var longitude: Double
23 | var latitude: Double
24 | }
25 | ```
26 |
27 | Once we have defined a Coordinate struct, let's create a mapper that parses out the values from the response and return the value of Coordinate type.
28 |
29 | **US2ExampleCoordinateTransformer Implementation**
30 |
31 | ```
32 | let longitudeKey = "longitude"
33 | let latitudeKey = "latitude"
34 |
35 | public class US2ExampleCoordinateTransformer : US2TransformerProtocol {
36 |
37 | public func transformValues(inputValues : Dictionary?) -> Any? {
38 |
39 | if let coordinateDictionary = inputValues as? Dictionary {
40 | if let unwrappedLongitude = coordinateDictionary[longitudeKey] {
41 | if let unwrappedLatitude = coordinateDictionary[latitudeKey] {
42 | return Coordinate(longitude : unwrappedLongitude, latitude : unwrappedLatitude)
43 | }
44 | }
45 | }
46 |
47 | return nil
48 | }
49 | }
50 | ```
51 |
52 | Now that we have created a transformeer, let's create some mapping for our business Object:
53 |
54 | **Business.plist**
55 |
56 |
57 | 
58 |
59 |
60 | After the creation of the mapping, perform a build **(⌘-B)**. The changes should be reflected accordingly in the internal `_Business.swift` class.
61 |
62 |
63 | ```
64 | import Foundation
65 | import US2MapperKit
66 |
67 | class _Business {
68 | var uuid : Double?
69 | var name : String?
70 | var coordinates : Coordinates?
71 |
72 | required init() {...}
73 |
74 | convenience init?(_ dictionary: Dictionary) {...}
75 | }
76 | ```
77 |
78 | After calling the fail-able initializer - or udpateWithDictionary method with a dictioanry representation - US2MapperKit will use the custom transformer to map the struct accordingly.
79 |
80 | Note: The the keys defined in the property mapping correspond to the keys in the dictionary of values passed to the ` public func transformValues(inputValues : Dictionary?) -> Any?` method defined by the protocol.
81 |
--------------------------------------------------------------------------------
/Source/US2MapperKit/Parsers/CollectionParser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CollectionParser.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | final class CollectionParser {
12 |
13 | // MARK Determines the type of representation to be mapped to an Array
14 |
15 | class func arrayRepresentation(fromValue data : AnyObject, ofType collectionSubType : String?, using instantiator : US2InstantiatorProtocol) -> [AnyObject] {
16 |
17 | if nativeDataTypes.containsValue(collectionSubType!) {
18 | if let unwrappedData = data as? Dictionary {
19 | return NativeValueArrayParser.arrayRepresentation(collectionSubType, data : unwrappedData, instantiator : instantiator)
20 | } else if let unwrappedData = data as? [AnyObject] {
21 | return NativeValueArrayParser.arrayRepresentation(collectionSubType, data : unwrappedData, instantiator : instantiator)
22 | }
23 | }
24 |
25 | if let unwrappedData = data as? Dictionary> {
26 | return ComplexValueArrayParser.arrayRepresentation(collectionSubType, data : unwrappedData, instantiator: instantiator)
27 | } else if let unwrappedData = data as? [Dictionary] {
28 | return ComplexValueArrayParser.arrayRepresentation(collectionSubType, data : unwrappedData, instantiator: instantiator)
29 | }
30 |
31 | return []
32 | }
33 |
34 | // MARK Determines the type of representation to be mapped to a Dictionary
35 |
36 | class func dictionaryRepresentation(fromValue data : AnyObject, ofType collectionSubType : String?, using instantiator : US2InstantiatorProtocol) -> Dictionary {
37 |
38 | if nativeDataTypes.containsValue(collectionSubType!) {
39 | if let unwrappedData = data as? Dictionary {
40 | return NativeValueDictionaryParser.dictionaryRepresentation(collectionSubType, data : unwrappedData, instantiator: instantiator)
41 | } else if let unwrappedData = data as? [AnyObject] {
42 | return NativeValueDictionaryParser.dictionaryRepresentation(collectionSubType, data : unwrappedData, instantiator: instantiator)
43 | }
44 | }
45 |
46 | if let unwrappedData = data as? Dictionary> {
47 | return ComplexValueDictionaryParser.dictionaryRepresentation(collectionSubType, data: unwrappedData, instantiator: instantiator)
48 | } else if let unwrappedData = data as? Dictionary {
49 | return ComplexValueDictionaryParser.dictionaryRepresentation(collectionSubType, data : unwrappedData, instantiator: instantiator)
50 | } else if let unwrappedData = data as? [Dictionary] {
51 | return ComplexValueDictionaryParser.dictionaryRepresentation(collectionSubType, data : unwrappedData, instantiator: instantiator)
52 | }
53 |
54 | return [:]
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/documentation/custom_transforms_enums.md:
--------------------------------------------------------------------------------
1 | ##Example - Enums Transformations
2 |
3 | As of version 0.2.0 of U2MapperKit, the ability to map enums via the `US2TransformerProtocol` as support was added. This ensures that we can return an a value of `Any` type. Let's look at a dictionary for a business object, and see how we can map an enum to represent the type business:
4 |
5 | **Response Dictionary**
6 |
7 | ```
8 | {
9 | 'business_uuid' : 9223123456754775807,
10 | 'business_name' : 'UsTwo Restaurant',
11 | 'business_type' : 'Lounge'
12 | }
13 | ```
14 |
15 | Unlike the model objects, US2MapperKit does not autogenerate enums, due to the fact they would be uncustomizable. This would prevent the developer from using the many features Swift offers with enums. For the purposes of the example, let's assume that a business_type key value parsed can be 'Lounge', 'Dinner', and 'Coffee Shop'. First, create an enum to represent the business type for our custom Business Object:
16 |
17 | **Enum Definition**
18 |
19 | ```
20 | enum BusinessType : Int {
21 | case Unknown = 0, Lounge, Dinner, CoffeeShop
22 | }
23 | ```
24 |
25 | Once we have defined a BusinessType enum, create a mapper that parses out the values from the response and return the BusinessType type enum value.
26 |
27 | **US2ExampleCoordinateTransformer Implementation**
28 |
29 | ```
30 | let businessTypeKey = "business_type"
31 |
32 | public class US2ExampleBusinessTypeTransformer : US2TransformerProtocol {
33 | public func transformValues(inputValues : Dictionary?) -> Any? {
34 |
35 | if let typeValue = inputValues![businessTypeKey] as? String {
36 | switch typeValue {
37 | case "Lounge":
38 | return BusinessType.Lounge
39 | case "Dinner":
40 | return BusinessType.Dinner
41 | case "CoffeeShop":
42 | return BusinessType.CoffeeShop
43 | default:
44 | return BusinessType.Unknown
45 | }
46 | }
47 | return nil
48 | }
49 | }
50 | ```
51 |
52 | Now that we have created a transformeer let's create some mapping for our business Object:
53 |
54 | **Business.plist**
55 |
56 |
57 | 
58 |
59 |
60 | After the creation of the mapping, perform a build **(⌘-B)**. The changes should be reflected accordingly in the internal `_Business.swift` class.
61 |
62 |
63 | ```
64 | import Foundation
65 | import US2MapperKit
66 |
67 | class _Business {
68 | var uuid : Double?
69 | var name : String?
70 | var businessType : BusinessType?
71 |
72 | required init() {...}
73 |
74 | convenience init?(_ dictionary: Dictionary) {...}
75 | }
76 |
77 | ```
78 | After calling the fail-able initializer - or udpateWithDictionary method with a dictionary representation - US2MapperKit will use the custom transformer to map the enumerator accordingly.
79 |
80 |
81 | Note: The the keys defined in the property mapping correspond to the keys in the dictionary of values passed to the ` public func transformValues(inputValues : Dictionary?) -> Any?` method defined by the protocol.
82 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/US2Instantiator.swift:
--------------------------------------------------------------------------------
1 | // US2MapperKit Generated Model
2 | // UPDATE LISCENSE HERE
3 |
4 | import Foundation
5 |
6 | enum US2MapperClassEnum: String {
7 | case _TestObjectEight = "TestObjectEight"
8 | case _TestObjectEleven = "TestObjectEleven"
9 | case _TestObjectFive = "TestObjectFive"
10 | case _TestObjectFour = "TestObjectFour"
11 | case _TestObjectNine = "TestObjectNine"
12 | case _TestObjectSeven = "TestObjectSeven"
13 | case _TestObjectSix = "TestObjectSix"
14 | case _TestObjectTen = "TestObjectTen"
15 | case _TestObjectThirteen = "TestObjectThirteen"
16 | case _TestObjectThree = "TestObjectThree"
17 | case _TestObjectTwelve = "TestObjectTwelve"
18 | case _TestObjectTwo = "TestObjectTwo"
19 | case _None = "None"
20 |
21 | func createObject(data : Dictionary) -> AnyObject? {
22 | switch self {
23 | case ._TestObjectEight:
24 | return TestObjectEight(data)
25 | case ._TestObjectEleven:
26 | return TestObjectEleven(data)
27 | case ._TestObjectFive:
28 | return TestObjectFive(data)
29 | case ._TestObjectFour:
30 | return TestObjectFour(data)
31 | case ._TestObjectNine:
32 | return TestObjectNine(data)
33 | case ._TestObjectSeven:
34 | return TestObjectSeven(data)
35 | case ._TestObjectSix:
36 | return TestObjectSix(data)
37 | case ._TestObjectTen:
38 | return TestObjectTen(data)
39 | case ._TestObjectThirteen:
40 | return TestObjectThirteen(data)
41 | case ._TestObjectThree:
42 | return TestObjectThree(data)
43 | case ._TestObjectTwelve:
44 | return TestObjectTwelve(data)
45 | case ._TestObjectTwo:
46 | return TestObjectTwo(data)
47 | case ._None:
48 | return nil
49 | }
50 | }
51 | }
52 |
53 | enum US2TransformerEnum: String {
54 | case _US2CompoundValueTransformer = "US2CompoundValueTransformer"
55 | case _US2ExampleStructTransformer = "US2ExampleStructTransformer"
56 | case _US2ExampleTupleTransformer = "US2ExampleTupleTransformer"
57 | case _US2ExampleClosureTransformer = "US2ExampleClosureTransformer"
58 | case _US2ExampleEnumTransformer = "US2ExampleEnumTransformer"
59 | case _None = "None"
60 |
61 | func transformer() -> US2TransformerProtocol? {
62 | switch self {
63 | case ._US2CompoundValueTransformer:
64 | return US2CompoundValueTransformer()
65 |
66 | case ._US2ExampleStructTransformer:
67 | return US2ExampleStructTransformer()
68 |
69 | case ._US2ExampleTupleTransformer:
70 | return US2ExampleTupleTransformer()
71 |
72 | case ._US2ExampleClosureTransformer:
73 | return US2ExampleClosureTransformer()
74 |
75 | case ._US2ExampleEnumTransformer:
76 | return US2ExampleEnumTransformer()
77 |
78 | case ._None:
79 | return nil }
80 | }
81 | }
82 |
83 | class US2Instantiator : US2InstantiatorProtocol {
84 |
85 | static let sharedInstance : US2Instantiator = US2Instantiator()
86 |
87 | func newInstance(ofType classname : String, withValue data : Dictionary) -> AnyObject? {
88 | return US2MapperClassEnum(rawValue: classname)?.createObject(data)
89 | }
90 |
91 | func transformerFromString(classString: String) -> US2TransformerProtocol? {
92 | return US2TransformerEnum(rawValue: classString)!.transformer()
93 | }
94 | }
--------------------------------------------------------------------------------
/documentation/custom_transforms.md:
--------------------------------------------------------------------------------
1 | ##Example - Custom Transformations
2 |
3 | To perform transformations of a single or multiple values, US2MapperKit provides the ability to map multiple values from a dictionary response, and process them using the `US2TransformerProtocol`. Currently all transformed output properties must be optional, and the script will error out with a description in the build log.
4 |
5 | ```
6 | public protocol US2TransformerProtocol {
7 | func transformValues(inputValues : Dictionary?) -> Any?
8 | }
9 | ```
10 |
11 | Transformations are great approach, especially for Date transforms by reusing the NSDateFormatter - and possibly creating attributed strings by reusing NSMutableParagraphStyles. Let's observe a response with a simple user object.
12 |
13 | **Response Dictionary**
14 |
15 | ```
16 | {
17 | "user_id" : 9223123456754776000,
18 | "first_name" : "John",
19 | "last_name" : "Doe"
20 | }
21 | ```
22 |
23 | Assuming the need to store the user's full name as a single property, the transformer implementation below takes in a user's first name and last name as a parsed dictionary of strings keyed according to the property mapping defined and transforms them into a single full name property value before being returned and assigned.
24 |
25 |
26 | **US2TransformerProtocol Implementation**
27 |
28 | ```
29 | let firstNameKey = "first_name"
30 | let lastNameKey = "last_name"
31 |
32 | public class US2FullNameValueTransformer : US2TransformerProtocol {
33 |
34 | public func transformValues(inputValues : Dictionary?) -> Any? {
35 | var fullNameString : String = ""
36 |
37 | if let componentDictionary = inputValues as? Dictionary {
38 |
39 | if let firstName = componentDictionary[firstNameKey] {
40 | fullNameString += firstName
41 | }
42 |
43 | if fullNameString.isEmpty == false { fullNameString += " " }
44 |
45 | if let lastName = componentDictionary[lastNameKey] {
46 | fullNameString += lastName
47 | }
48 | }
49 |
50 | if fullNameString.isEmpty { return nil }
51 |
52 | return fullNameString
53 | }
54 | }
55 | ```
56 |
57 | To implement the transformer as part of the model mapping, observe how the **key** property in the mapping has become an array and takes in multiple values to transform into a fullName property. To use the custom transformer created above, add the **transformer** key to the property mapping defining which trasnformer class to use.
58 |
59 | **User.plist**
60 |
61 |
62 | 
63 |
64 |
65 | Note: The the keys defined in the property mapping correspond to the keys in the dictionary of values passed to the ` public func transformValues(inputValues : Dictionary?) -> Any?` method defined by the protocol.
66 |
67 |
68 | ###Compound Value Transformer
69 |
70 | Currently the only packaged trasnformer shipped with the framework is the `US2CompoundValueTransformer` which takes in a dictionary of values per `US2TransformerProtocol`, and creates a compound output value from the values passed into it.
71 |
72 | There is potential for more transformers to be added in future releases.
73 |
--------------------------------------------------------------------------------
/documentation/custom_transforms_closures.md:
--------------------------------------------------------------------------------
1 | ##Example - Closure Transformations
2 |
3 | As of version 0.2.0 of U2MapperKit, the ability to map closures via the `US2TransformerProtocol` as support was added. This ensures that we can return an a value of `Any` type. Let's look at a dictionary for a business object, and see how we can map a function/closure.
4 |
5 | **Response Dictionary**
6 |
7 | ```
8 | {
9 | 'business_uuid' : 9223123456754775807,
10 | 'business_name' : 'UsTwo Restaurant',
11 | 'business_facebook_id' : '123456789323123',
12 | 'business_yelp_id' : '409283409238409',
13 | }
14 | ```
15 | Let's create a mapper that parses out the values from the response which, based on the identifier, returns the clousure:
16 |
17 | **US2ExampleSocialClosureTransformer Implementation**
18 |
19 | ```
20 | import Foundation
21 | import UIKit
22 |
23 | let facebookIDKey = "facebook_id"
24 | let yelpIDKey = "yelp_id"
25 |
26 | public class US2ExampleSocialClosureTransformer : US2TransformerProtocol {
27 |
28 | public func transformValues(inputValues : Dictionary?) -> Any? {
29 | if let facebookdentifier = inputValues![facebookIDKey] as? String {
30 | func routeToFacebookApp() {
31 | if UIApplication.sharedApplication().openURL(NSURL(string:"fb://")!) {
32 | let facebookAppLink = "fb://profile/\(facebookdentifier)"
33 | UIApplication.sharedApplication().openURL(NSURL(string: facebookAppLink)!)
34 | } else {
35 | let itunesLink = "itms://itunes.apple.com/us/app/apple-store/id284882215?mt=8"
36 | UIApplication.sharedApplication().openURL(NSURL(string: itunesLink)!)
37 | }
38 | }
39 | return routeToFacebookApp
40 | }
41 |
42 | if let yelpIdentifier = inputValues![yelpIDKey] as? String {
43 |
44 | func routeToFacebookApp() {
45 | if UIApplication.sharedApplication().openURL(NSURL(string:"yelp://")!) {
46 | let yelpAppLink = "yelp:///biz/\(yelpIdentifier)"
47 | UIApplication.sharedApplication().openURL(NSURL(string:yelpAppLink)!)
48 | } else {
49 | let itunesLink = "itms://itunes.apple.com/us/app/apple-store/id284910350?mt=8"
50 | UIApplication.sharedApplication().openURL(NSURL(string: itunesLink)!)
51 | }
52 | }
53 |
54 | return routeToYelpApp
55 | }
56 | return nil
57 | }
58 | }
59 |
60 | ```
61 |
62 | Now that we have created a transformer, let's create some mapping to map our closures to an isntance variable.
63 |
64 | **Business.plist**
65 |
66 |
67 | 
68 |
69 |
70 | After the creation of the mapping, perform a build **(⌘-B)**. The changes should be reflected accordingly in the internal `_Business.swift` class.
71 |
72 |
73 | ```
74 | import Foundation
75 | import US2MapperKit
76 |
77 | class _Business {
78 | var uuid : Double?
79 | var name : String?
80 | var routeToFacebook : (() -> Void)?
81 | var routeToYelp : (() -> Void)?
82 |
83 | required init() {...}
84 |
85 | convenience init?(_ dictionary: Dictionary) {...}
86 | }
87 | ```
88 |
89 | After calling the fail-able initializer - or udpateWithDictionary method with a dictioanry representation - US2MapperKit will use the custom transformer to map the custom closure accordingly. Although this is a simple and abstract scenerio, the potential for this funtionality has many outcomes to be explored.
90 |
91 | Note: The the keys defined in the property mapping correspond to the keys in the dictionary of values passed to the ` public func transformValues(inputValues : Dictionary?) -> Any?` method defined by the protocol.
92 |
--------------------------------------------------------------------------------
/documentation/optional_value_types.md:
--------------------------------------------------------------------------------
1 | ##Example - Optional Value Types
2 |
3 | US2MapperKit supports mapping basic data types including `String`, `Int`, `Double`, `Float` and `Bool`. Let's look at a simple example for mapping basic datatypes for a `Dictionary` response for a basic business case
4 |
5 | **Response Dictionary**
6 |
7 | ```
8 | {
9 | 'business_uuid' : 9223123456754775807,
10 | 'business_name' : 'UsTwo Restaurant',
11 | 'business_rating' : 5,
12 | 'business_longitude' : 40.7053319,
13 | 'business_latitude' : -74.0129945,
14 | 'business_open' : 1
15 | }
16 | ```
17 |
18 | After receiving the data dictionary, the next step is to model the response into a class and map it accordingly. Unlike other mapping frameworks, where the developer needs to model the object first prior to mapping the response, US2MapperKit takes care of generating the model by creating a plist mapping for a given model object. Let's go ahead and create a mapping for our `Business` model object, and add it to the mapping folder configured during installation.
19 |
20 |
21 | **Business.plist**
22 |
23 |
24 | 
25 |
26 | For each property that US2MapperKit will generate in the final model object, define a dictionary within the plist to represent that property. For each property, at minimum, we must define a **key** and a **type** entry. The **key** maps to the value of the response dictionary, and **type** defines the Swift datatype for that property.
27 |
28 | Now that the Model Mapping is defined and within our configured mapping folder, perform a build **(⌘-B)**. Next, navigate to the configured model output folder, and add the generated files to the project. NOTE: This only has to be done once, unless the name of the Model object changes. As a developer, one should not have to add the created files again, and they should change accordingly when the build script is run.
29 |
30 | From this example we'll find there has been created an internal `_Business.swift` file, an external `Business.swift` class that extends from the latter, and a `US2Instantiator.swift`. Lets take a take a high-level look at the output.
31 |
32 |
33 | **_Business.swift**
34 |
35 |
36 | ```
37 | import Foundation
38 | import US2MapperKit
39 |
40 | class _Business {
41 |
42 | var rating : Int?
43 | var uuid : Double?
44 | var longitude : Float?
45 | var latitude : Float?
46 | var open : Bool?
47 | var name : String?
48 |
49 | required init() {...}
50 |
51 | convenience init?(_ dictionary: Dictionary) {...}
52 | }
53 | ```
54 |
55 | The internal file is where all the magic happens. At a high level, it provides a required initializer, and a [Fail-able Initializer](https://developer.apple.com/swift/blog/?id=17) which takes in a `Dictionary` to be parsed. In the case that the parsing fails, the fail-able initializer will return nil. In the case where all of the properties are optional, and there are missing values in the response, the fail-able initializer will return an instance with the missing values accordingly.
56 |
57 | **Business.swift**
58 |
59 |
60 | ```
61 | import Foundation
62 |
63 | class Business : _Business {
64 | // Add Custom Logic Here
65 | }
66 | ```
67 |
68 | The external file is for custom logic, and is only generated once, and will go unchanged if there is an update to the mapping. As a developer, one can add properties, methods, and implement any protocol as needed. The internal class is only there to hold reference to the values from the response dictionary is is being passed.
69 |
70 | ###Default Values
71 | To assign a default value definition for an optional property, follow the example found in the [Default Value Definitions](/documentation/default_values.md) section of this documentation.
72 |
--------------------------------------------------------------------------------
/Source/US2MapperKit/Parsers/Parser.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Parser.swift
3 | // US2MapperKit
4 | //
5 | // Created by Anton Doudarev on 7/17/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Parser {
12 |
13 | final class func retrieveValue(from dictionary : Dictionary, applying propertyMapping : Dictionary, employing instantiator : US2InstantiatorProtocol, defaultsEnabled : Bool) -> Any? {
14 |
15 | if propertyMapping[US2MapperTransformerKey] != nil {
16 | return Transformer.transformedValue(from: dictionary, applying : propertyMapping, employing : instantiator)
17 | }
18 |
19 | if let jsonKey = propertyMapping[US2MapperJSONKey] as? String {
20 | if let dataType = propertyMapping[US2MapperTypeKey] as? String {
21 |
22 | let subType = propertyMapping[US2MapperCollectionSubTypeKey] as? String
23 |
24 | if let retrievedValue: AnyObject = dictionaryValueForKey(jsonKey, dictionary: dictionary) {
25 | return parsedValue(forValue : retrievedValue, dataType, subType, instantiator : instantiator)
26 | } else if let retrievedDefaultValue: AnyObject = propertyMapping[US2MapperDefaultKey] {
27 |
28 | if defaultsEnabled {
29 | return parsedValue(forValue : retrievedDefaultValue, dataType, subType, instantiator : instantiator)
30 | } else {
31 | return nil
32 | }
33 | }
34 | }
35 | }
36 |
37 | return nil
38 | }
39 |
40 | final class func parsedValue(forValue value : AnyObject, _ dataType : String, _ subType: String?, instantiator : US2InstantiatorProtocol) -> AnyObject? {
41 |
42 | if nativeDataTypes.containsValue(dataType) {
43 |
44 | return NativeTypeParser.nativeRepresentation(fromValue : value, asType : dataType)
45 |
46 | } else if collectionTypes.containsValue(dataType) {
47 |
48 | switch dataType {
49 | case US2DataTypeArray:
50 | return CollectionParser.arrayRepresentation(fromValue : value, ofType : subType, using : instantiator)
51 | case US2DataTypeDictionary:
52 | return CollectionParser.dictionaryRepresentation(fromValue : value, ofType : subType, using : instantiator)
53 | default:
54 | if let unwrappedValue = value as? Dictionary {
55 | return ComplexTypeParser.complexObject(fromValue: unwrappedValue, ofType: subType, using : instantiator)
56 | }
57 | }
58 | } else {
59 | return instantiator.newInstance(ofType: dataType, withValue: value as! Dictionary)
60 | }
61 |
62 | return nil
63 | }
64 |
65 | final class func dictionaryValueForKey(key : String, dictionary : Dictionary) -> AnyObject? {
66 | var keys = key.componentsSeparatedByString(".")
67 | var nestedDictionary = dictionary
68 |
69 | for var x = 0; x < keys.count; x++ {
70 | if x >= (keys.count - 1) {
71 | if let finalValue: AnyObject = nestedDictionary[keys[x]] {
72 | return finalValue
73 | } else {
74 | break
75 | }
76 | } else if let nextLevelDictionary = nestedDictionary[keys[x]] as? Dictionary {
77 | nestedDictionary = nextLevelDictionary
78 | } else {
79 | break
80 | }
81 | }
82 | return nil
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Source/US2MapperKit/US2Mapper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // US2Mapper.swift
3 | // US2Mapper
4 | //
5 | // Created by Anton Doudarev on 6/22/15.
6 | // Copyright © 2015 Ustwo. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public protocol US2InstantiatorProtocol {
12 | func newInstance(ofType classname : String, withValue data : Dictionary) -> AnyObject?
13 | func transformerFromString(classString: String) -> US2TransformerProtocol?
14 | }
15 |
16 | public protocol US2TransformerProtocol {
17 | func transformValues(inputValues : Dictionary?) -> Any?
18 | }
19 |
20 | public func typeCast(object: Any?) -> U? {
21 | if let typed = object as? U {
22 | return typed
23 | }
24 | return nil
25 | }
26 |
27 | extension Array {
28 | func containsValue(obj: T) -> Bool {
29 | return self.filter({$0 as? T == obj}).count > 0
30 | }
31 | }
32 |
33 | var propertyMappings : Dictionary>> = Dictionary()
34 |
35 | let US2MapperJSONKey = "key"
36 | let US2MapperTypeKey = "type"
37 | let US2MapperNonOptionalKey = "nonoptional"
38 | let US2MapperDefaultKey = "default"
39 | let US2MapperTransformerKey = "transformer"
40 | let US2MapperCollectionSubTypeKey = "collection_subtype"
41 |
42 | let US2DataTypeString = "String"
43 | let US2DataTypeInt = "Int"
44 | let US2DataTypeDouble = "Double"
45 | let US2DataTypeFloat = "Float"
46 | let US2DataTypeBool = "Bool"
47 | let US2DataTypeArray = "Array"
48 | let US2DataTypeDictionary = "Dictionary"
49 |
50 | let nativeDataTypes = [US2DataTypeString, US2DataTypeInt, US2DataTypeDouble, US2DataTypeFloat, US2DataTypeBool]
51 | let collectionTypes = [US2DataTypeArray, US2DataTypeDictionary]
52 |
53 | final public class US2Mapper {
54 |
55 | public class func mapValues(from dictionary : Dictionary, forType classType : String , employing instantiator : US2InstantiatorProtocol, defaultsEnabled : Bool) -> Dictionary? {
56 |
57 | if let mappingConfiguration = retrieveMappingConfiguration(classType) {
58 |
59 | // Dictionary to store parsed values to be returned
60 | var retrievedValueDictionary = Dictionary()
61 |
62 | for (propertyKey, propertyMapping) in mappingConfiguration {
63 | retrievedValueDictionary[propertyKey] = Parser.retrieveValue(from : dictionary, applying : propertyMapping, employing : instantiator, defaultsEnabled : defaultsEnabled)
64 | }
65 |
66 | if defaultsEnabled == false {
67 | return retrievedValueDictionary
68 | }
69 |
70 | if Validator.validateResponse(forValues: retrievedValueDictionary, mappedTo : mappingConfiguration, forType : classType, withData : dictionary) {
71 | return retrievedValueDictionary
72 | }
73 | }
74 |
75 | return nil
76 | }
77 |
78 | class func retrieveMappingConfiguration(className : String) -> Dictionary>? {
79 | if let mappingconfiguration = propertyMappings[className] {
80 | return mappingconfiguration
81 | } else {
82 | if let mappingPath = NSBundle(forClass: self).pathForResource(className, ofType: "plist") {
83 | let tempMapping = NSDictionary(contentsOfFile: mappingPath) as? Dictionary>
84 |
85 | if tempMapping!.isEmpty { return nil }
86 |
87 | propertyMappings[className] = tempMapping
88 | return tempMapping!
89 | } else {
90 | return nil
91 | }
92 | }
93 | }
94 | }
95 |
96 |
--------------------------------------------------------------------------------
/documentation/installation.md:
--------------------------------------------------------------------------------
1 | ##US2MapperKit - Installation
2 |
3 | ####Manual Install
4 |
5 | 1. Clone the [US2MapperKit](git@github.com:ustwo/US2MapperKit.git) repository
6 | 2. Add the contents of the Source Directory to the project
7 | 3. In the Project's Root Folder create a new folder that will contain all the mapping plist files
8 | 4. In the application targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase”. Create a Run Script with the following content:
9 |
10 | ```
11 | SCRIPT_LOCATION=$(find ${PODS_ROOT} -name modelgen-swift.py | head -n 1)
12 | python $SCRIPT_LOCATION -v 0.1 -i $PROJECT_DIR/$PROJECT_NAME/Mappings/ -o $PROJECT_DIR/$PROJECT_NAME/Model/
13 |
14 | ```
15 |
16 | 4. Move the newly created Run Script phase to the second listing right below the "Target Dependencies" task
17 |
18 |
19 | ####CocoaPods
20 |
21 | 1. Edit the project's podfile
22 |
23 | ```
24 | pod 'US2MapperKit', :git => 'https://github.com/ustwo/US2MapperKit.git'
25 | ```
26 | 2. Install US2MapperKit by running
27 |
28 | ```
29 | pod install
30 | ```
31 | 3. In the Project's Root Folder create a new folder that will contain all the mapping plist files
32 | 4. Navigate to the application targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase”. Create a Run Script with the following contents:
33 |
34 | NOTE: The script below differs for installation via Carthage
35 |
36 | ```
37 | SCRIPT_LOCATION=$(find ${PODS_ROOT} -name modelgen-swift.py | head -n 1)
38 | python $SCRIPT_LOCATION -v 0.1 -i $PROJECT_DIR/$PROJECT_NAME/Mappings/ -o $PROJECT_DIR/$PROJECT_NAME/Model/
39 | ```
40 | 5. Move the newly created Run Script phase to the second listing right below the "Target Dependencies" task
41 |
42 |
43 | ####Carthage
44 |
45 | The installation instruction below are a for OSX and iOS, follow the extra steps documented when installing for iOS.
46 |
47 | #####Installation
48 |
49 | 1. Create/Update the Cartfile with with the following
50 |
51 | ```
52 | #US2MapperKit
53 | git "https://github.com/ustwo/US2MapperKit.git"
54 | ```
55 | 2. Run `carthage update`. This will fetch dependencies into a [Carthage/Checkouts][] folder, then build each one.
56 | 3. In the application targets’ “General” settings tab, in the “Embedded Binaries” section, drag and drop each framework for use from the Carthage/Build folder on disk.
57 | 3. In the project's root folder create a new folder that will contain all the mapping plist files
58 | 4. Navigate to the application targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase”. Create a Run Script with the following contents:
59 |
60 | NOTE: The script below differs for installation via Cocoapods
61 |
62 | ```
63 | SCRIPT_LOCATION=$(find $SRCROOT -name modelgen-swift.py | head -n 1)
64 | python $SCRIPT_LOCATION -v 0.1 -i $PROJECT_DIR/$PROJECT_NAME/Mapping/ -o $PROJECT_DIR/$PROJECT_NAME/Model/
65 | ```
66 | 5. Move the newly created Run Script phase to the second listing right below the "Target Dependencies" task
67 |
68 |
69 | #####iOS Installation
70 |
71 | 1. Follow the installation instruction above. Once complete, perform the following steps
72 | (If you have setup a carthage build task for iOS already skip to Step 5)
73 | 2. Navigate to the targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase”. Create a Run Script with the following content:
74 |
75 | ```
76 | /usr/local/bin/carthage copy-frameworks
77 | ```
78 |
79 | 3. Add the paths to the frameworks you want to use under “Input Files” within the carthage build phase as follows e.g.:
80 |
81 | ```
82 | $(SRCROOT)/Carthage/Build/iOS/US2MapperKit.framework
83 |
84 | ```
85 |
86 |
87 | ####Script Reference
88 |
89 | The model-building script generates a model for part of a build task within the project. Below is a reference for the input parameters.
90 |
91 | ```
92 | Parameter Description:
93 | -v defines the version (currently 0.1)
94 | -i defines the location where the plist mappings are stored (`$PROJECT_DIR/$PROJECT_NAME/Mappings`)
95 | -o defines the output directory for the model objects (`$PROJECT_DIR/$PROJECT_NAME/Model`)
96 | ```
97 |
--------------------------------------------------------------------------------
/US2MapperKit/US2MapperKit/US2MapperKit.xcodeproj/xcshareddata/xcschemes/US2MapperKit - OSX.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
94 |
100 |
101 |
102 |
103 |
105 |
106 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/US2MapperKit/US2MapperKit/US2MapperKit.xcodeproj/xcshareddata/xcschemes/US2MapperKit - iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
94 |
100 |
101 |
102 |
103 |
105 |
106 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectFour.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectFour {
5 |
6 | var optionalInt : Int?
7 | var optionalBool : Bool?
8 | var optionalString : String?
9 | var optionalDouble : Double?
10 | var optionalFloat : Float?
11 |
12 | var non_optionalDouble : Double
13 | var non_optionalFloat : Float
14 | var non_optionalInt : Int
15 | var non_optionalBool : Bool
16 | var non_optionalString : String
17 |
18 | required init(_non_optionalDouble : Double,
19 | _non_optionalFloat : Float,
20 | _non_optionalInt : Int,
21 | _non_optionalBool : Bool,
22 | _non_optionalString : String) {
23 |
24 | non_optionalDouble = _non_optionalDouble
25 | non_optionalFloat = _non_optionalFloat
26 | non_optionalInt = _non_optionalInt
27 | non_optionalBool = _non_optionalBool
28 | non_optionalString = _non_optionalString
29 | }
30 |
31 | convenience init?(_ dictionary: Dictionary) {
32 |
33 | let dynamicTypeString = "\(self.dynamicType)"
34 | let className = dynamicTypeString.componentsSeparatedByString(".").last
35 |
36 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
37 |
38 | let temp_non_optionalDouble : Double = typeCast(valuesDict["non_optionalDouble"])!
39 | let temp_non_optionalFloat : Float = typeCast(valuesDict["non_optionalFloat"])!
40 | let temp_non_optionalInt : Int = typeCast(valuesDict["non_optionalInt"])!
41 | let temp_non_optionalBool : Bool = typeCast(valuesDict["non_optionalBool"])!
42 | let temp_non_optionalString : String = typeCast(valuesDict["non_optionalString"])!
43 |
44 | self.init(_non_optionalDouble : temp_non_optionalDouble,
45 | _non_optionalFloat : temp_non_optionalFloat,
46 | _non_optionalInt : temp_non_optionalInt,
47 | _non_optionalBool : temp_non_optionalBool,
48 | _non_optionalString : temp_non_optionalString)
49 |
50 | if let unwrapped_optionalInt : Any = valuesDict["optionalInt"] {
51 | optionalInt = typeCast(unwrapped_optionalInt)
52 | }
53 |
54 | if let unwrapped_optionalBool : Any = valuesDict["optionalBool"] {
55 | optionalBool = typeCast(unwrapped_optionalBool)
56 | }
57 |
58 | if let unwrapped_optionalString : Any = valuesDict["optionalString"] {
59 | optionalString = typeCast(unwrapped_optionalString)
60 | }
61 |
62 | if let unwrapped_optionalDouble : Any = valuesDict["optionalDouble"] {
63 | optionalDouble = typeCast(unwrapped_optionalDouble)
64 | }
65 |
66 | if let unwrapped_optionalFloat : Any = valuesDict["optionalFloat"] {
67 | optionalFloat = typeCast(unwrapped_optionalFloat)
68 | }
69 |
70 | } else {
71 | self.init(_non_optionalDouble : Double(),
72 | _non_optionalFloat : Float(),
73 | _non_optionalInt : Int(),
74 | _non_optionalBool : Bool(),
75 | _non_optionalString : String())
76 |
77 | return nil
78 | }
79 | }
80 |
81 | func updateWithDictionary(dictionary: Dictionary) {
82 |
83 | let dynamicTypeString = "\(self.dynamicType)"
84 | let className = dynamicTypeString.componentsSeparatedByString(".").last
85 |
86 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
87 | if let unwrapped_non_optionalDouble : Any = valuesDict["non_optionalDouble"] {
88 | non_optionalDouble = typeCast(unwrapped_non_optionalDouble)!
89 | }
90 |
91 | if let unwrapped_optionalInt : Any = valuesDict["optionalInt"] {
92 | optionalInt = typeCast(unwrapped_optionalInt)
93 | }
94 |
95 | if let unwrapped_non_optionalFloat : Any = valuesDict["non_optionalFloat"] {
96 | non_optionalFloat = typeCast(unwrapped_non_optionalFloat)!
97 | }
98 |
99 | if let unwrapped_non_optionalInt : Any = valuesDict["non_optionalInt"] {
100 | non_optionalInt = typeCast(unwrapped_non_optionalInt)!
101 | }
102 |
103 | if let unwrapped_optionalBool : Any = valuesDict["optionalBool"] {
104 | optionalBool = typeCast(unwrapped_optionalBool)
105 | }
106 |
107 | if let unwrapped_optionalString : Any = valuesDict["optionalString"] {
108 | optionalString = typeCast(unwrapped_optionalString)
109 | }
110 |
111 | if let unwrapped_optionalDouble : Any = valuesDict["optionalDouble"] {
112 | optionalDouble = typeCast(unwrapped_optionalDouble)
113 | }
114 |
115 | if let unwrapped_optionalFloat : Any = valuesDict["optionalFloat"] {
116 | optionalFloat = typeCast(unwrapped_optionalFloat)
117 | }
118 |
119 | if let unwrapped_non_optionalBool : Any = valuesDict["non_optionalBool"] {
120 | non_optionalBool = typeCast(unwrapped_non_optionalBool)!
121 | }
122 |
123 | if let unwrapped_non_optionalString : Any = valuesDict["non_optionalString"] {
124 | non_optionalString = typeCast(unwrapped_non_optionalString)!
125 | }
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectEleven.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectEleven {
5 |
6 | var optionalInt : Int?
7 | var optionalBool : Bool?
8 | var optionalString : String?
9 | var optionalDouble : Double?
10 | var optionalFloat : Float?
11 |
12 | var non_optionalDouble : Double
13 | var non_optionalFloat : Float
14 | var non_optionalInt : Int
15 | var non_optionalBool : Bool
16 | var non_optionalString : String
17 |
18 | required init(_non_optionalDouble : Double,
19 | _non_optionalFloat : Float,
20 | _non_optionalInt : Int,
21 | _non_optionalBool : Bool,
22 | _non_optionalString : String) {
23 |
24 | non_optionalDouble = _non_optionalDouble
25 | non_optionalFloat = _non_optionalFloat
26 | non_optionalInt = _non_optionalInt
27 | non_optionalBool = _non_optionalBool
28 | non_optionalString = _non_optionalString
29 | }
30 |
31 | convenience init?(_ dictionary: Dictionary) {
32 |
33 | let dynamicTypeString = "\(self.dynamicType)"
34 | let className = dynamicTypeString.componentsSeparatedByString(".").last
35 |
36 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
37 |
38 | let temp_non_optionalDouble : Double = typeCast(valuesDict["non_optionalDouble"])!
39 | let temp_non_optionalFloat : Float = typeCast(valuesDict["non_optionalFloat"])!
40 | let temp_non_optionalInt : Int = typeCast(valuesDict["non_optionalInt"])!
41 | let temp_non_optionalBool : Bool = typeCast(valuesDict["non_optionalBool"])!
42 | let temp_non_optionalString : String = typeCast(valuesDict["non_optionalString"])!
43 |
44 | self.init(_non_optionalDouble : temp_non_optionalDouble,
45 | _non_optionalFloat : temp_non_optionalFloat,
46 | _non_optionalInt : temp_non_optionalInt,
47 | _non_optionalBool : temp_non_optionalBool,
48 | _non_optionalString : temp_non_optionalString)
49 |
50 | if let unwrapped_optionalInt : Any = valuesDict["optionalInt"] {
51 | optionalInt = typeCast(unwrapped_optionalInt)
52 | }
53 |
54 | if let unwrapped_optionalBool : Any = valuesDict["optionalBool"] {
55 | optionalBool = typeCast(unwrapped_optionalBool)
56 | }
57 |
58 | if let unwrapped_optionalString : Any = valuesDict["optionalString"] {
59 | optionalString = typeCast(unwrapped_optionalString)
60 | }
61 |
62 | if let unwrapped_optionalDouble : Any = valuesDict["optionalDouble"] {
63 | optionalDouble = typeCast(unwrapped_optionalDouble)
64 | }
65 |
66 | if let unwrapped_optionalFloat : Any = valuesDict["optionalFloat"] {
67 | optionalFloat = typeCast(unwrapped_optionalFloat)
68 | }
69 |
70 | } else {
71 | self.init(_non_optionalDouble : Double(),
72 | _non_optionalFloat : Float(),
73 | _non_optionalInt : Int(),
74 | _non_optionalBool : Bool(),
75 | _non_optionalString : String())
76 |
77 | return nil
78 | }
79 | }
80 |
81 | func updateWithDictionary(dictionary: Dictionary) {
82 |
83 | let dynamicTypeString = "\(self.dynamicType)"
84 | let className = dynamicTypeString.componentsSeparatedByString(".").last
85 |
86 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
87 | if let unwrapped_non_optionalDouble : Any = valuesDict["non_optionalDouble"] {
88 | non_optionalDouble = typeCast(unwrapped_non_optionalDouble)!
89 | }
90 |
91 | if let unwrapped_optionalInt : Any = valuesDict["optionalInt"] {
92 | optionalInt = typeCast(unwrapped_optionalInt)
93 | }
94 |
95 | if let unwrapped_non_optionalFloat : Any = valuesDict["non_optionalFloat"] {
96 | non_optionalFloat = typeCast(unwrapped_non_optionalFloat)!
97 | }
98 |
99 | if let unwrapped_non_optionalInt : Any = valuesDict["non_optionalInt"] {
100 | non_optionalInt = typeCast(unwrapped_non_optionalInt)!
101 | }
102 |
103 | if let unwrapped_optionalBool : Any = valuesDict["optionalBool"] {
104 | optionalBool = typeCast(unwrapped_optionalBool)
105 | }
106 |
107 | if let unwrapped_optionalString : Any = valuesDict["optionalString"] {
108 | optionalString = typeCast(unwrapped_optionalString)
109 | }
110 |
111 | if let unwrapped_optionalDouble : Any = valuesDict["optionalDouble"] {
112 | optionalDouble = typeCast(unwrapped_optionalDouble)
113 | }
114 |
115 | if let unwrapped_optionalFloat : Any = valuesDict["optionalFloat"] {
116 | optionalFloat = typeCast(unwrapped_optionalFloat)
117 | }
118 |
119 | if let unwrapped_non_optionalBool : Any = valuesDict["non_optionalBool"] {
120 | non_optionalBool = typeCast(unwrapped_non_optionalBool)!
121 | }
122 |
123 | if let unwrapped_non_optionalString : Any = valuesDict["non_optionalString"] {
124 | non_optionalString = typeCast(unwrapped_non_optionalString)!
125 | }
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectThree.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectThree {
5 |
6 | var optionalInt : Int?
7 | var optionalBool : Bool?
8 | var optionalString : String?
9 | var optionalDouble : Double?
10 | var optionalFloat : Float?
11 |
12 | var non_optionalDouble : Double
13 | var non_optionalInt : Int
14 | var non_optionalFloat : Float
15 | var non_optionalBool : Bool
16 | var non_optionalString : String
17 |
18 | required init(_non_optionalDouble : Double,
19 | _non_optionalInt : Int,
20 | _non_optionalFloat : Float,
21 | _non_optionalBool : Bool,
22 | _non_optionalString : String) {
23 |
24 | non_optionalDouble = _non_optionalDouble
25 | non_optionalInt = _non_optionalInt
26 | non_optionalFloat = _non_optionalFloat
27 | non_optionalBool = _non_optionalBool
28 | non_optionalString = _non_optionalString
29 | }
30 |
31 | convenience init?(_ dictionary: Dictionary) {
32 |
33 | let dynamicTypeString = "\(self.dynamicType)"
34 | let className = dynamicTypeString.componentsSeparatedByString(".").last
35 |
36 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
37 |
38 | let temp_non_optionalDouble : Double = typeCast(valuesDict["non_optionalDouble"])!
39 | let temp_non_optionalInt : Int = typeCast(valuesDict["non_optionalInt"])!
40 | let temp_non_optionalFloat : Float = typeCast(valuesDict["non_optionalFloat"])!
41 | let temp_non_optionalBool : Bool = typeCast(valuesDict["non_optionalBool"])!
42 | let temp_non_optionalString : String = typeCast(valuesDict["non_optionalString"])!
43 |
44 | self.init(_non_optionalDouble : temp_non_optionalDouble,
45 | _non_optionalInt : temp_non_optionalInt,
46 | _non_optionalFloat : temp_non_optionalFloat,
47 | _non_optionalBool : temp_non_optionalBool,
48 | _non_optionalString : temp_non_optionalString)
49 |
50 | if let unwrapped_optionalInt : Any = valuesDict["optionalInt"] {
51 | optionalInt = typeCast(unwrapped_optionalInt)
52 | }
53 |
54 | if let unwrapped_optionalBool : Any = valuesDict["optionalBool"] {
55 | optionalBool = typeCast(unwrapped_optionalBool)
56 | }
57 |
58 | if let unwrapped_optionalString : Any = valuesDict["optionalString"] {
59 | optionalString = typeCast(unwrapped_optionalString)
60 | }
61 |
62 | if let unwrapped_optionalDouble : Any = valuesDict["optionalDouble"] {
63 | optionalDouble = typeCast(unwrapped_optionalDouble)
64 | }
65 |
66 | if let unwrapped_optionalFloat : Any = valuesDict["optionalFloat"] {
67 | optionalFloat = typeCast(unwrapped_optionalFloat)
68 | }
69 |
70 | } else {
71 | self.init(_non_optionalDouble : Double(),
72 | _non_optionalInt : Int(),
73 | _non_optionalFloat : Float(),
74 | _non_optionalBool : Bool(),
75 | _non_optionalString : String())
76 |
77 | return nil
78 | }
79 | }
80 |
81 | func updateWithDictionary(dictionary: Dictionary) {
82 |
83 | let dynamicTypeString = "\(self.dynamicType)"
84 | let className = dynamicTypeString.componentsSeparatedByString(".").last
85 |
86 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
87 | if let unwrapped_non_optionalDouble : Any = valuesDict["non_optionalDouble"] {
88 | non_optionalDouble = typeCast(unwrapped_non_optionalDouble)!
89 | }
90 |
91 | if let unwrapped_non_optionalInt : Any = valuesDict["non_optionalInt"] {
92 | non_optionalInt = typeCast(unwrapped_non_optionalInt)!
93 | }
94 |
95 | if let unwrapped_non_optionalFloat : Any = valuesDict["non_optionalFloat"] {
96 | non_optionalFloat = typeCast(unwrapped_non_optionalFloat)!
97 | }
98 |
99 | if let unwrapped_optionalInt : Any = valuesDict["optionalInt"] {
100 | optionalInt = typeCast(unwrapped_optionalInt)
101 | }
102 |
103 | if let unwrapped_optionalBool : Any = valuesDict["optionalBool"] {
104 | optionalBool = typeCast(unwrapped_optionalBool)
105 | }
106 |
107 | if let unwrapped_optionalString : Any = valuesDict["optionalString"] {
108 | optionalString = typeCast(unwrapped_optionalString)
109 | }
110 |
111 | if let unwrapped_optionalDouble : Any = valuesDict["optionalDouble"] {
112 | optionalDouble = typeCast(unwrapped_optionalDouble)
113 | }
114 |
115 | if let unwrapped_optionalFloat : Any = valuesDict["optionalFloat"] {
116 | optionalFloat = typeCast(unwrapped_optionalFloat)
117 | }
118 |
119 | if let unwrapped_non_optionalBool : Any = valuesDict["non_optionalBool"] {
120 | non_optionalBool = typeCast(unwrapped_non_optionalBool)!
121 | }
122 |
123 | if let unwrapped_non_optionalString : Any = valuesDict["non_optionalString"] {
124 | non_optionalString = typeCast(unwrapped_non_optionalString)!
125 | }
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectTwelve.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectTwelve {
5 |
6 | var optionalInt : Int?
7 | var optionalBool : Bool?
8 | var optionalString : String?
9 | var optionalDouble : Double?
10 | var optionalFloat : Float?
11 |
12 | var non_optionalDouble : Double
13 | var non_optionalFloat : Float
14 | var non_optionalInt : Int
15 | var non_optionalBool : Bool
16 | var non_optionalString : String
17 |
18 | required init(_non_optionalDouble : Double,
19 | _non_optionalFloat : Float,
20 | _non_optionalInt : Int,
21 | _non_optionalBool : Bool,
22 | _non_optionalString : String) {
23 |
24 | non_optionalDouble = _non_optionalDouble
25 | non_optionalFloat = _non_optionalFloat
26 | non_optionalInt = _non_optionalInt
27 | non_optionalBool = _non_optionalBool
28 | non_optionalString = _non_optionalString
29 | }
30 |
31 | convenience init?(_ dictionary: Dictionary) {
32 |
33 | let dynamicTypeString = "\(self.dynamicType)"
34 | let className = dynamicTypeString.componentsSeparatedByString(".").last
35 |
36 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
37 |
38 | let temp_non_optionalDouble : Double = typeCast(valuesDict["non_optionalDouble"])!
39 | let temp_non_optionalFloat : Float = typeCast(valuesDict["non_optionalFloat"])!
40 | let temp_non_optionalInt : Int = typeCast(valuesDict["non_optionalInt"])!
41 | let temp_non_optionalBool : Bool = typeCast(valuesDict["non_optionalBool"])!
42 | let temp_non_optionalString : String = typeCast(valuesDict["non_optionalString"])!
43 |
44 | self.init(_non_optionalDouble : temp_non_optionalDouble,
45 | _non_optionalFloat : temp_non_optionalFloat,
46 | _non_optionalInt : temp_non_optionalInt,
47 | _non_optionalBool : temp_non_optionalBool,
48 | _non_optionalString : temp_non_optionalString)
49 |
50 | if let unwrapped_optionalInt : Any = valuesDict["optionalInt"] {
51 | optionalInt = typeCast(unwrapped_optionalInt)
52 | }
53 |
54 | if let unwrapped_optionalBool : Any = valuesDict["optionalBool"] {
55 | optionalBool = typeCast(unwrapped_optionalBool)
56 | }
57 |
58 | if let unwrapped_optionalString : Any = valuesDict["optionalString"] {
59 | optionalString = typeCast(unwrapped_optionalString)
60 | }
61 |
62 | if let unwrapped_optionalDouble : Any = valuesDict["optionalDouble"] {
63 | optionalDouble = typeCast(unwrapped_optionalDouble)
64 | }
65 |
66 | if let unwrapped_optionalFloat : Any = valuesDict["optionalFloat"] {
67 | optionalFloat = typeCast(unwrapped_optionalFloat)
68 | }
69 |
70 | } else {
71 | self.init(_non_optionalDouble : Double(),
72 | _non_optionalFloat : Float(),
73 | _non_optionalInt : Int(),
74 | _non_optionalBool : Bool(),
75 | _non_optionalString : String())
76 |
77 | return nil
78 | }
79 | }
80 |
81 | func updateWithDictionary(dictionary: Dictionary) {
82 |
83 | let dynamicTypeString = "\(self.dynamicType)"
84 | let className = dynamicTypeString.componentsSeparatedByString(".").last
85 |
86 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
87 | if let unwrapped_non_optionalDouble : Any = valuesDict["non_optionalDouble"] {
88 | non_optionalDouble = typeCast(unwrapped_non_optionalDouble)!
89 | }
90 |
91 | if let unwrapped_optionalInt : Any = valuesDict["optionalInt"] {
92 | optionalInt = typeCast(unwrapped_optionalInt)
93 | }
94 |
95 | if let unwrapped_non_optionalFloat : Any = valuesDict["non_optionalFloat"] {
96 | non_optionalFloat = typeCast(unwrapped_non_optionalFloat)!
97 | }
98 |
99 | if let unwrapped_non_optionalInt : Any = valuesDict["non_optionalInt"] {
100 | non_optionalInt = typeCast(unwrapped_non_optionalInt)!
101 | }
102 |
103 | if let unwrapped_optionalBool : Any = valuesDict["optionalBool"] {
104 | optionalBool = typeCast(unwrapped_optionalBool)
105 | }
106 |
107 | if let unwrapped_optionalString : Any = valuesDict["optionalString"] {
108 | optionalString = typeCast(unwrapped_optionalString)
109 | }
110 |
111 | if let unwrapped_optionalDouble : Any = valuesDict["optionalDouble"] {
112 | optionalDouble = typeCast(unwrapped_optionalDouble)
113 | }
114 |
115 | if let unwrapped_optionalFloat : Any = valuesDict["optionalFloat"] {
116 | optionalFloat = typeCast(unwrapped_optionalFloat)
117 | }
118 |
119 | if let unwrapped_non_optionalBool : Any = valuesDict["non_optionalBool"] {
120 | non_optionalBool = typeCast(unwrapped_non_optionalBool)!
121 | }
122 |
123 | if let unwrapped_non_optionalString : Any = valuesDict["non_optionalString"] {
124 | non_optionalString = typeCast(unwrapped_non_optionalString)!
125 | }
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectNine.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectNine {
5 |
6 | var optionalArrayIntType : [Int]?
7 | var optionalArrayStringType : [String]?
8 | var optionalArrayDoubleType : [Double]?
9 | var optionalArrayFloatType : [Float]?
10 |
11 | var non_optionalArrayFloatType : [Float]
12 | var non_optionalArrayDoubleType : [Double]
13 | var non_optionalArrayIntType : [Int]
14 | var non_optionalArrayStringType : [String]
15 |
16 | required init(_non_optionalArrayFloatType : [Float],
17 | _non_optionalArrayDoubleType : [Double],
18 | _non_optionalArrayIntType : [Int],
19 | _non_optionalArrayStringType : [String]) {
20 |
21 | non_optionalArrayFloatType = _non_optionalArrayFloatType
22 | non_optionalArrayDoubleType = _non_optionalArrayDoubleType
23 | non_optionalArrayIntType = _non_optionalArrayIntType
24 | non_optionalArrayStringType = _non_optionalArrayStringType
25 | }
26 |
27 | convenience init?(_ dictionary: Dictionary) {
28 |
29 | let dynamicTypeString = "\(self.dynamicType)"
30 | let className = dynamicTypeString.componentsSeparatedByString(".").last
31 |
32 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
33 |
34 | let temp_non_optionalArrayFloatType : [Float] = typeCast(valuesDict["non_optionalArrayFloatType"])!
35 | let temp_non_optionalArrayDoubleType : [Double] = typeCast(valuesDict["non_optionalArrayDoubleType"])!
36 | let temp_non_optionalArrayIntType : [Int] = typeCast(valuesDict["non_optionalArrayIntType"])!
37 | let temp_non_optionalArrayStringType : [String] = typeCast(valuesDict["non_optionalArrayStringType"])!
38 |
39 | self.init(_non_optionalArrayFloatType : temp_non_optionalArrayFloatType,
40 | _non_optionalArrayDoubleType : temp_non_optionalArrayDoubleType,
41 | _non_optionalArrayIntType : temp_non_optionalArrayIntType,
42 | _non_optionalArrayStringType : temp_non_optionalArrayStringType)
43 |
44 | if let unwrapped_optionalArrayIntType : Any = valuesDict["optionalArrayIntType"] {
45 | optionalArrayIntType = typeCast(unwrapped_optionalArrayIntType)
46 | }
47 |
48 | if let unwrapped_optionalArrayStringType : Any = valuesDict["optionalArrayStringType"] {
49 | optionalArrayStringType = typeCast(unwrapped_optionalArrayStringType)
50 | }
51 |
52 | if let unwrapped_optionalArrayDoubleType : Any = valuesDict["optionalArrayDoubleType"] {
53 | optionalArrayDoubleType = typeCast(unwrapped_optionalArrayDoubleType)
54 | }
55 |
56 | if let unwrapped_optionalArrayFloatType : Any = valuesDict["optionalArrayFloatType"] {
57 | optionalArrayFloatType = typeCast(unwrapped_optionalArrayFloatType)
58 | }
59 |
60 | } else {
61 | self.init(_non_optionalArrayFloatType : [Float](),
62 | _non_optionalArrayDoubleType : [Double](),
63 | _non_optionalArrayIntType : [Int](),
64 | _non_optionalArrayStringType : [String]())
65 |
66 | return nil
67 | }
68 | }
69 |
70 | func updateWithDictionary(dictionary: Dictionary) {
71 |
72 | let dynamicTypeString = "\(self.dynamicType)"
73 | let className = dynamicTypeString.componentsSeparatedByString(".").last
74 |
75 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
76 | if let unwrapped_optionalArrayIntType : Any = valuesDict["optionalArrayIntType"] {
77 | optionalArrayIntType = typeCast(unwrapped_optionalArrayIntType)
78 | }
79 |
80 | if let unwrapped_optionalArrayStringType : Any = valuesDict["optionalArrayStringType"] {
81 | optionalArrayStringType = typeCast(unwrapped_optionalArrayStringType)
82 | }
83 |
84 | if let unwrapped_non_optionalArrayFloatType : Any = valuesDict["non_optionalArrayFloatType"] {
85 | non_optionalArrayFloatType = typeCast(unwrapped_non_optionalArrayFloatType)!
86 | }
87 |
88 | if let unwrapped_non_optionalArrayDoubleType : Any = valuesDict["non_optionalArrayDoubleType"] {
89 | non_optionalArrayDoubleType = typeCast(unwrapped_non_optionalArrayDoubleType)!
90 | }
91 |
92 | if let unwrapped_non_optionalArrayIntType : Any = valuesDict["non_optionalArrayIntType"] {
93 | non_optionalArrayIntType = typeCast(unwrapped_non_optionalArrayIntType)!
94 | }
95 |
96 | if let unwrapped_non_optionalArrayStringType : Any = valuesDict["non_optionalArrayStringType"] {
97 | non_optionalArrayStringType = typeCast(unwrapped_non_optionalArrayStringType)!
98 | }
99 |
100 | if let unwrapped_optionalArrayDoubleType : Any = valuesDict["optionalArrayDoubleType"] {
101 | optionalArrayDoubleType = typeCast(unwrapped_optionalArrayDoubleType)
102 | }
103 |
104 | if let unwrapped_optionalArrayFloatType : Any = valuesDict["optionalArrayFloatType"] {
105 | optionalArrayFloatType = typeCast(unwrapped_optionalArrayFloatType)
106 | }
107 | }
108 | }
109 | }
--------------------------------------------------------------------------------
/US2MapperKit/Shared Test Cases/Classes/Internal/_TestObjectTen.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | class _TestObjectTen {
5 |
6 | var optionalDictionaryFloatType : Dictionary?
7 | var optionalDictionaryStringType : Dictionary?
8 | var optionalDictionaryIntType : Dictionary?
9 | var optionalDictionaryDoubleType : Dictionary?
10 |
11 | var non_optionalDictionaryDoubleType : Dictionary
12 | var non_optionalDictionaryIntType : Dictionary
13 | var non_optionalDictionaryFloatType : Dictionary
14 | var non_optionalDictionaryStringType : Dictionary
15 |
16 | required init(_non_optionalDictionaryDoubleType : Dictionary,
17 | _non_optionalDictionaryIntType : Dictionary,
18 | _non_optionalDictionaryFloatType : Dictionary,
19 | _non_optionalDictionaryStringType : Dictionary) {
20 |
21 | non_optionalDictionaryDoubleType = _non_optionalDictionaryDoubleType
22 | non_optionalDictionaryIntType = _non_optionalDictionaryIntType
23 | non_optionalDictionaryFloatType = _non_optionalDictionaryFloatType
24 | non_optionalDictionaryStringType = _non_optionalDictionaryStringType
25 | }
26 |
27 | convenience init?(_ dictionary: Dictionary) {
28 |
29 | let dynamicTypeString = "\(self.dynamicType)"
30 | let className = dynamicTypeString.componentsSeparatedByString(".").last
31 |
32 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {
33 |
34 | let temp_non_optionalDictionaryDoubleType : Dictionary = typeCast(valuesDict["non_optionalDictionaryDoubleType"])!
35 | let temp_non_optionalDictionaryIntType : Dictionary = typeCast(valuesDict["non_optionalDictionaryIntType"])!
36 | let temp_non_optionalDictionaryFloatType : Dictionary = typeCast(valuesDict["non_optionalDictionaryFloatType"])!
37 | let temp_non_optionalDictionaryStringType : Dictionary = typeCast(valuesDict["non_optionalDictionaryStringType"])!
38 |
39 | self.init(_non_optionalDictionaryDoubleType : temp_non_optionalDictionaryDoubleType,
40 | _non_optionalDictionaryIntType : temp_non_optionalDictionaryIntType,
41 | _non_optionalDictionaryFloatType : temp_non_optionalDictionaryFloatType,
42 | _non_optionalDictionaryStringType : temp_non_optionalDictionaryStringType)
43 |
44 | if let unwrapped_optionalDictionaryFloatType : Any = valuesDict["optionalDictionaryFloatType"] {
45 | optionalDictionaryFloatType = typeCast(unwrapped_optionalDictionaryFloatType)
46 | }
47 |
48 | if let unwrapped_optionalDictionaryStringType : Any = valuesDict["optionalDictionaryStringType"] {
49 | optionalDictionaryStringType = typeCast(unwrapped_optionalDictionaryStringType)
50 | }
51 |
52 | if let unwrapped_optionalDictionaryIntType : Any = valuesDict["optionalDictionaryIntType"] {
53 | optionalDictionaryIntType = typeCast(unwrapped_optionalDictionaryIntType)
54 | }
55 |
56 | if let unwrapped_optionalDictionaryDoubleType : Any = valuesDict["optionalDictionaryDoubleType"] {
57 | optionalDictionaryDoubleType = typeCast(unwrapped_optionalDictionaryDoubleType)
58 | }
59 |
60 | } else {
61 | self.init(_non_optionalDictionaryDoubleType : Dictionary(),
62 | _non_optionalDictionaryIntType : Dictionary(),
63 | _non_optionalDictionaryFloatType : Dictionary(),
64 | _non_optionalDictionaryStringType : Dictionary())
65 |
66 | return nil
67 | }
68 | }
69 |
70 | func updateWithDictionary(dictionary: Dictionary) {
71 |
72 | let dynamicTypeString = "\(self.dynamicType)"
73 | let className = dynamicTypeString.componentsSeparatedByString(".").last
74 |
75 | if let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {
76 | if let unwrapped_non_optionalDictionaryDoubleType : Any = valuesDict["non_optionalDictionaryDoubleType"] {
77 | non_optionalDictionaryDoubleType = typeCast(unwrapped_non_optionalDictionaryDoubleType)!
78 | }
79 |
80 | if let unwrapped_optionalDictionaryFloatType : Any = valuesDict["optionalDictionaryFloatType"] {
81 | optionalDictionaryFloatType = typeCast(unwrapped_optionalDictionaryFloatType)
82 | }
83 |
84 | if let unwrapped_optionalDictionaryStringType : Any = valuesDict["optionalDictionaryStringType"] {
85 | optionalDictionaryStringType = typeCast(unwrapped_optionalDictionaryStringType)
86 | }
87 |
88 | if let unwrapped_optionalDictionaryIntType : Any = valuesDict["optionalDictionaryIntType"] {
89 | optionalDictionaryIntType = typeCast(unwrapped_optionalDictionaryIntType)
90 | }
91 |
92 | if let unwrapped_non_optionalDictionaryIntType : Any = valuesDict["non_optionalDictionaryIntType"] {
93 | non_optionalDictionaryIntType = typeCast(unwrapped_non_optionalDictionaryIntType)!
94 | }
95 |
96 | if let unwrapped_non_optionalDictionaryFloatType : Any = valuesDict["non_optionalDictionaryFloatType"] {
97 | non_optionalDictionaryFloatType = typeCast(unwrapped_non_optionalDictionaryFloatType)!
98 | }
99 |
100 | if let unwrapped_non_optionalDictionaryStringType : Any = valuesDict["non_optionalDictionaryStringType"] {
101 | non_optionalDictionaryStringType = typeCast(unwrapped_non_optionalDictionaryStringType)!
102 | }
103 |
104 | if let unwrapped_optionalDictionaryDoubleType : Any = valuesDict["optionalDictionaryDoubleType"] {
105 | optionalDictionaryDoubleType = typeCast(unwrapped_optionalDictionaryDoubleType)
106 | }
107 | }
108 | }
109 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/ustwo/US2MapperKit)
2 | [](https://github.com/Carthage/Carthage)
3 | [](https://github.com/ustwo/US2MapperKit)
4 | [](https://github.com/ustwo/US2MapperKit)
5 | #US2MapperKit
6 | 
7 |
8 | Inspired by [CSMapper](https://github.com/marcammann/CSMapper) and [Mogenerator](https://github.com/rentzsch/mogenerator), US2MapperKit is an an extremely lightweight mapping framework designed specifically for Swift 1.2, and Swift 2.0.
9 |
10 | Unlike previous frameworks, where an object model is manually created by the developer then retrofitted with a mapping framework at a later point, US2MapperKit takes a mapping-first approach. By mapping against dictionary data up front, US2MapperKit generates the model objects based on the mapping, and allows for the extensibility inspired by the [Protocol-Oriented Programming](https://developer.apple.com/videos/wwdc/2015/?id=408) talk at WWDC.
11 |
12 | ##Core Concept
13 |
14 | 
15 |
16 | The simple example above demonstrates the inner workings of the US2MapperKit. In this example we will attemp to map a Person object returned in the form a dictionary. The first step is to manually generate a plist representing the data that is being returned. This plist defines properties, data types, the mapping keys associated with the response dictionary, and any transformation that needs to be applied. Once defined, a build-time script will generate two model object files representing the model mapping.
17 |
18 | The first class generated in the diagram represents the internal `_Person.swift` class, which contains script-generated property definitions, along two initializers, one required, and one fail-able. The generated fail-able initializer takes in a `Dictionary` input value which is parsed to the model. The internal files purpose is to support the framework by mapping the response data and should not be modified by the developer since the script will regenerate it every time the project is built.
19 |
20 | The second class generated is the `Person.swift` which inherits from the internal `_Person.swift` class. This provides a means for developer to append any custom logic, properties, or implementations of protocols as needed during the development process. This class is only generated once, and will never be overwritten during the build task. Thus updating the model mapping will not affect any logic defined in the external class.
21 |
22 | ##Features
23 |
24 | * Auto generation of model objects via .plists files
25 | * Optional & Non-Optional support for:
26 | * String
27 | * Int
28 | * Double
29 | * Float
30 | * Bool
31 | * Collections Support for:
32 | * Array\
33 | * Dictionary\
34 | * Complex Type Support (stand alone, and in collections)
35 | * Default Value Definitions
36 | * Mapping Nested Values
37 | * Complex Transformations
38 | * Structs, Enums, Closures, Tuples via Transformations
39 |
40 | ##Basic Use
41 |
42 | ####Initialization with Dictionary
43 |
44 | Once configured per the [Installation](/documentation/installation.md) instructions:
45 |
46 | 1. Create a plist model mapping and place it in the mapping folder defined during installation.
47 | 2. Build the target, navigate to the output directory defined during the installation process, and add the generated files to the project.
48 | 3. Map the data to an instance, call the fail-able initializer generated by US2MapperKit with the `Dictionary` data to parse.
49 |
50 | ```
51 | let newInstance = TestModelObject(dataDictionary)
52 | ```
53 |
54 | ####Update with Dictionary
55 |
56 | Once an instance has been initialized, we can pass a new dictionary with values to update for the current instance by calling `updateWithDictionary(dictionary : Dictionary?)`. Note that only the values which are being passed within will be updated, defaults values are ignored unline the initialization
57 |
58 | ```
59 | let instance = TestModelObject(dataDictionary)
60 | let newValuesDictionary = [... : ...]
61 |
62 | // Updates the current values only with the new values received, defaults in mapping are ignored
63 | instance.updateWithDictionary(newValuesDictionary)
64 |
65 | ```
66 |
67 | ####Examples
68 |
69 | Below is a list of examples for the supported features by US2MapperKit. Each provides an overall view on how to setup the model mapping file, and short examples of the outputs generated by pre-packaged script within the framework.
70 |
71 | * [Optional Types](/documentation/optional_value_types.md)
72 | * [Non-Optional Types](/documentation/non_optional_value_types.md)
73 | * [Collection Types](/documentation/collection_types.md)
74 | * [Complex Types](/documentation/complex_value_types.md)
75 | * [Default Value Definitions](/documentation/default_values.md)
76 | * [Mapping Against Nested Values](/documentation/nested_mapping.md)
77 | * [Custom Transformations](/documentation/custom_transforms.md)
78 | * [Structs Mapping](/documentation/custom_transforms_struct.md)
79 | * [Enum Mapping](/documentation/custom_transforms_enums.md)
80 | * [Closures Mapping](/documentation/custom_transforms_closures.md)
81 | * [Tuples Mapping](/documentation/custom_transforms_tuples.md)
82 |
83 | ##Troubleshooting
84 |
85 | - [Enabling Debug Mode](/documentation/enable_debug_mode.md)
86 | - [Swift 1.2 / 2.0 Compatibility](/documentation/compatibility_issues.md)
87 |
88 | ##Updates
89 |
90 | - [Change Log](/documentation/changelog.md)
91 |
92 | ##Future Enahancements
93 |
94 | * Mapping Inheritance (Configuration to Inherit from NSManagedObject / Realm Object)
95 | * Xcode Plug-in
96 |
97 | ## License
98 |
99 | The MIT License (MIT)
100 |
101 | Copyright (c) 2015 ustwo studio inc (www.ustwo.com)
102 |
103 | Permission is hereby granted, free of charge, to any person obtaining a copy
104 | of this software and associated documentation files (the "Software"), to deal
105 | in the Software without restriction, including without limitation the rights
106 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
107 | copies of the Software, and to permit persons to whom the Software is
108 | furnished to do so, subject to the following conditions:
109 |
110 | The above copyright notice and this permission notice shall be included in all
111 | copies or substantial portions of the Software.
112 |
113 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
114 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
115 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
116 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
117 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
118 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
119 | SOFTWARE.
120 |
--------------------------------------------------------------------------------
/Source/ModelScript/modelgen-swift.py:
--------------------------------------------------------------------------------
1 | #!/usr/local/bin/python
2 | import plistlib
3 | import os
4 | import sys
5 | import getopt
6 | import dircache
7 | import glob
8 | import commands
9 |
10 | FOLDER_INTERNAL_PREFIX = "Classes/Internal/_"
11 | FOLDER_EXTERNAL_PREFIX = "Classes/"
12 |
13 | PROPERTY_TYPE_STRING = "String"
14 | PROPERTY_TYPE_DOUBLE = "Double"
15 | PROPERTY_TYPE_FLOAT = "Float"
16 | PROPERTY_TYPE_INT = "Int"
17 | PROPERTY_TYPE_BOOL = "Bool"
18 | PROPERTY_TYPE_ARRAY = "Array"
19 | PROPERTY_TYPE_DICTIONARY = "Dictionary"
20 |
21 | NATIVE_PROPERTY_TYPES = [PROPERTY_TYPE_STRING, PROPERTY_TYPE_DOUBLE, PROPERTY_TYPE_FLOAT, PROPERTY_TYPE_INT, PROPERTY_TYPE_BOOL]
22 |
23 | MAPPING_KEY_TYPE = "type"
24 | MAPPING_KEY_DEFAULT = "default"
25 | MAPPING_KEY_KEY = "key"
26 | MAPPING_KEY_NONOPTIONAL = "nonoptional"
27 | MAPPING_KEY_TRANSFORMER = "transformer"
28 | MAPPING_KEY_COLLECTION_SUBTYPE = "collection_subtype"
29 |
30 | STRING_IMPORT_FOUNDATION = "import Foundation\n"
31 | STRING_REQUIRED_INIT_START = "\n\trequired init("
32 | STRING_MAP_VALUES_DICT_START = "\n\n\tprivate func setValues("
33 | STRING_MAP_DICT_START = '\n\n\tfunc updateWithDictionary(dictionary: Dictionary) {\n\n\t\tlet dynamicTypeString = "\(self.dynamicType)"\n\t\tlet className = dynamicTypeString.componentsSeparatedByString(".").last\n\n\t\tif let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : false) {'
34 |
35 | STRING_FAILABLE_INIT_START = '\tconvenience init?(_ dictionary: Dictionary) {\n\n\t\tlet dynamicTypeString = "\(self.dynamicType)"\n\t\tlet className = dynamicTypeString.componentsSeparatedByString(".").last\n\n\t\tif let valuesDict = US2Mapper.mapValues(from: dictionary, forType: className!, employing: US2Instantiator.sharedInstance, defaultsEnabled : true) {'
36 | STRING_FAILABLE_INIT_SUPER_START = '\t\n\t\t\tself.init('
37 | STRING_FILE_INTRO = '// US2MapperKit Generated Model\n// UPDATE LISCENSE HERE\n\n'
38 | STRING_PROPERTY_VAR = " var"
39 |
40 | STRING_CLASS_FROM_STRING_METHOD = "\n\nstatic let sharedInstance : US2Instantiator = US2Instantiator()\n\nfunc newInstance(ofType classname : String, withValue data : Dictionary) -> AnyObject? {\n\t\tswitch classname {\n"
41 |
42 | STRING_USMAPPER_IMPORT = "\n"
43 | STRING_USMAPPER_INHERITENCE = "\nclass US2Instantiator : US2InstantiatorProtocol {\n\n"
44 |
45 | def generate_model(mappinglist, output_directory, version):
46 |
47 | for mapping in mappinglist:
48 | filename = mapping[mapping.rindex('/',0,-1)+1:-1] if mapping.endswith('/') else mapping[mapping.rindex('/')+1:]
49 | classname = filename.split('.', 1 )[0]
50 |
51 | mappingPlist = plistlib.readPlist(mapping)
52 |
53 | validate_class_mapping_configuration(classname, mappingPlist)
54 |
55 | generate_internal_file(mappingPlist, classname, output_directory)
56 | generate_external_file_if_needed(classname, output_directory)
57 |
58 | generate_internal_instantiator_file(mappinglist, output_directory)
59 |
60 |
61 | '''
62 | External Model File Generation
63 | '''
64 | def generate_external_file_if_needed(classname, class_directory):
65 |
66 | filename = class_directory + classname + '.swift'
67 |
68 | if os.path.exists(filename):
69 | return None
70 |
71 | if not os.path.exists(os.path.dirname(filename)):
72 | os.makedirs(os.path.dirname(filename))
73 |
74 | outputfile = open(filename, "wba")
75 |
76 | outputfile.write(STRING_IMPORT_FOUNDATION + '\nclass ' + classname + ' : _' + classname + ' {\n\n}')
77 | outputfile.close();
78 |
79 |
80 | '''
81 | Internal Model File Generation
82 | '''
83 | def generate_internal_file(mappingPlist, classname, class_directory):
84 |
85 | filename = class_directory + 'Internal/_'+ classname + '.swift'
86 |
87 | if not os.path.exists(os.path.dirname(filename)):
88 | os.makedirs(os.path.dirname(filename))
89 |
90 | outputfile = open(filename, "wba")
91 |
92 | outputfile.write(STRING_IMPORT_FOUNDATION + STRING_USMAPPER_IMPORT + '\nclass _' + classname + ' {\n')
93 |
94 | append_optional_property_definitions(outputfile, mappingPlist)
95 | append_non_optional_property_definitions(outputfile, mappingPlist)
96 | append_required_initializer(outputfile, mappingPlist)
97 | append_failable_initializer(outputfile, mappingPlist)
98 | #append_map_values(outputfile, mappingPlist)
99 | append_map_dictionary_setter(outputfile, mappingPlist)
100 | outputfile.write('\n} ')
101 | outputfile.close();
102 |
103 |
104 | '''
105 | Appeand Properties
106 | '''
107 | def append_optional_property_definitions(classfile, mappingPlist):
108 | classfile.write('\n')
109 | mappingKeys = mappingPlist.keys()
110 |
111 | for propertyName in mappingKeys:
112 | propertyType = mappingPlist[propertyName][MAPPING_KEY_TYPE]
113 | collectionSubtype = ''
114 |
115 | if MAPPING_KEY_COLLECTION_SUBTYPE in mappingPlist[propertyName].keys():
116 | collectionSubtype = mappingPlist[propertyName][MAPPING_KEY_COLLECTION_SUBTYPE]
117 |
118 | if propertyType == PROPERTY_TYPE_ARRAY:
119 | if MAPPING_KEY_NONOPTIONAL not in mappingPlist[propertyName].keys() or mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] != 'true':
120 | append_array_instance_property(classfile, propertyName, collectionSubtype, True)
121 |
122 | elif propertyType == PROPERTY_TYPE_DICTIONARY:
123 | if MAPPING_KEY_NONOPTIONAL not in mappingPlist[propertyName].keys() or mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] != 'true':
124 | append_dictionary_instance_property(classfile, propertyName, collectionSubtype, True)
125 | else:
126 | if MAPPING_KEY_NONOPTIONAL not in mappingPlist[propertyName].keys() or mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] != 'true':
127 | append_instance_property(classfile, propertyName, propertyType, True)
128 |
129 |
130 | def append_non_optional_property_definitions(classfile, mappingPlist):
131 | classfile.write('\n')
132 |
133 | for propertyName in mappingPlist.keys():
134 | propertyType = mappingPlist[propertyName][MAPPING_KEY_TYPE]
135 | collectionSubtype = ''
136 |
137 | if MAPPING_KEY_COLLECTION_SUBTYPE in mappingPlist[propertyName].keys():
138 | collectionSubtype = mappingPlist[propertyName][MAPPING_KEY_COLLECTION_SUBTYPE]
139 |
140 | if propertyType == PROPERTY_TYPE_ARRAY:
141 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys() and mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
142 | append_array_instance_property(classfile, propertyName, collectionSubtype, False)
143 |
144 | elif propertyType == PROPERTY_TYPE_DICTIONARY:
145 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys() and mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
146 | append_dictionary_instance_property(classfile, propertyName, collectionSubtype, False)
147 | else:
148 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys() and mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
149 | append_instance_property(classfile, propertyName, propertyType, False)
150 |
151 |
152 | def append_instance_property(classfile, propertyname, datatype, optional):
153 | classfile.write(STRING_PROPERTY_VAR + ' ' + propertyname + ' : ' + datatype + '{}\n'.format('?' if optional else ''))
154 |
155 | def append_array_instance_property(classfile, propertyname, collectionSubtype, optional):
156 | classfile.write(STRING_PROPERTY_VAR + ' ' + propertyname + ' : [' + collectionSubtype + ']{}\n'.format('?' if optional else ''))
157 |
158 | def append_dictionary_instance_property(classfile, propertyname, collectionSubtype, optional):
159 | classfile.write(STRING_PROPERTY_VAR + ' ' + propertyname + ' : Dictionary{}\n'.format('?' if optional else ''))
160 |
161 |
162 | '''
163 | Append Required Initializer
164 | '''
165 | def append_required_initializer(classFile, mappingPlist):
166 | classFile.write(STRING_REQUIRED_INIT_START)
167 | firstPropertyWritten = True
168 |
169 | for propertyName in mappingPlist.keys():
170 | propertyType = mappingPlist[propertyName][MAPPING_KEY_TYPE]
171 |
172 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys() and mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
173 | append_required_initializer_non_optional_property(classFile, mappingPlist, propertyName, propertyType, firstPropertyWritten)
174 | firstPropertyWritten = False
175 |
176 | classFile.write(') {\n ')
177 | append_required_initializer_value_assignments(classFile, mappingPlist)
178 | classFile.write('\n\t}\n\n')
179 |
180 |
181 | def append_required_initializer_value_assignments(classFile, mappingPlist):
182 | for propertyName in mappingPlist.keys():
183 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys():
184 | if mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
185 | classFile.write('\n ')
186 | classFile.write(propertyName + ' = _' + propertyName )
187 |
188 |
189 | def append_required_initializer_non_optional_property(classFile, mappingPlist, propertyName, propertyType, isFirstProperty):
190 | if propertyType == PROPERTY_TYPE_ARRAY:
191 | collectionSubtype = mappingPlist[propertyName][MAPPING_KEY_COLLECTION_SUBTYPE]
192 | classFile.write('{}_'.format('' if isFirstProperty else ',\n\t\t\t\t ') + propertyName + ' : [' + collectionSubtype + ']')
193 | elif propertyType == PROPERTY_TYPE_DICTIONARY:
194 | collectionSubtype = mappingPlist[propertyName][MAPPING_KEY_COLLECTION_SUBTYPE]
195 | classFile.write('{}_'.format('' if isFirstProperty else ',\n\t\t\t\t ') + propertyName + ' : Dictionary')
196 | else:
197 | classFile.write('{}_'.format('' if isFirstProperty else ',\n\t\t\t\t ') + propertyName + ' : ' + propertyType)
198 |
199 |
200 | '''
201 | Append Failable Initializer
202 | '''
203 | def append_failable_initializer(classFile, mappingPlist):
204 |
205 | classFile.write(STRING_FAILABLE_INIT_START)
206 |
207 | append_failable_initializer_tempValues(classFile, mappingPlist)
208 |
209 | classFile.write(STRING_FAILABLE_INIT_SUPER_START)
210 |
211 | isFirstLine = True
212 |
213 | for propertyName in mappingPlist.keys():
214 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys() and mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
215 | classFile.write('{}_'.format('' if isFirstLine else ',\n\t\t\t\t\t ') + propertyName + ' : temp_' + propertyName + '')
216 | isFirstLine = False
217 |
218 | classFile.write(') \n\t\t')
219 |
220 | append_failable_initializer_typecasting(classFile, mappingPlist)
221 |
222 | print xcode_version()
223 |
224 | if xcode_version() == 7.0:
225 | classFile.write(' \n\t\t} else {\n\t\t\treturn nil\n\t\t}\n\t}')
226 | else:
227 | append_swift_1_2_failable_reinitialization(classFile, mappingPlist)
228 |
229 |
230 | def append_swift_1_2_failable_reinitialization(classFile, mappingPlist):
231 |
232 | classFile.write(' \n } else {\n self.init(')
233 | isFirstLine = True
234 |
235 | for propertyName in mappingPlist.keys():
236 | propertyType = mappingPlist[propertyName][MAPPING_KEY_TYPE]
237 | collectionSubtype = ''
238 |
239 | if MAPPING_KEY_COLLECTION_SUBTYPE in mappingPlist[propertyName].keys():
240 | collectionSubtype = mappingPlist[propertyName][MAPPING_KEY_COLLECTION_SUBTYPE]
241 |
242 | if propertyType == PROPERTY_TYPE_ARRAY:
243 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys() and mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
244 | append_array_failed_initialiser_property(classFile, propertyName, propertyType, collectionSubtype, False, isFirstLine)
245 | isFirstLine = False
246 |
247 | elif propertyType == PROPERTY_TYPE_DICTIONARY:
248 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys() and mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
249 | append_dictionary_failed_initialiser_property(classFile, propertyName, propertyType, collectionSubtype, False, isFirstLine)
250 | isFirstLine = False
251 | else:
252 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys() and mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
253 | append_failed_initialiser_property(classFile, propertyName, propertyType, False, isFirstLine)
254 | isFirstLine = False
255 |
256 | classFile.write(')\n\n\t\t\treturn nil\n\t\t}\n\t}')
257 |
258 |
259 | def append_failable_initializer_tempValues(classFile, mappingPlist):
260 | classFile.write('\n')
261 |
262 | for propertyName in mappingPlist.keys():
263 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys() and mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
264 | propertyType = mappingPlist[propertyName][MAPPING_KEY_TYPE]
265 | append_failable_initializer_non_optional_property_typecast(classFile, mappingPlist, propertyName, propertyType)
266 |
267 | classFile.write('\n')
268 |
269 |
270 | def append_failable_initializer_optional_temp_properties(classFile, mappingPlist, propertyName, propertyType):
271 | if propertyType == PROPERTY_TYPE_ARRAY:
272 | collectionSubtype = mappingPlist[propertyName][MAPPING_KEY_COLLECTION_SUBTYPE]
273 | classFile.write('\t\t\tvar temp_' + propertyName + ' : [' + collectionSubtype + ']?')
274 | elif propertyType == PROPERTY_TYPE_DICTIONARY:
275 | collectionSubtype = mappingPlist[propertyName][MAPPING_KEY_COLLECTION_SUBTYPE]
276 | classFile.write('\t\t\tvar temp_' + propertyName + ' : Dictionary?')
277 | else:
278 | classFile.write('\t\t\tvar temp_' + propertyName + ' : ' + propertyType + '?' )
279 |
280 |
281 | def append_failable_initializer_non_optional_property_typecast(classFile, mappingPlist, propertyName, propertyType):
282 | if propertyType == PROPERTY_TYPE_ARRAY:
283 | collectionSubtype = mappingPlist[propertyName][MAPPING_KEY_COLLECTION_SUBTYPE]
284 | classFile.write('\n\t\t\tlet temp_' + propertyName + ' : [' + collectionSubtype + ']' + ' = typeCast(valuesDict["' + propertyName + '"])!')
285 | elif propertyType == PROPERTY_TYPE_DICTIONARY:
286 | collectionSubtype = mappingPlist[propertyName][MAPPING_KEY_COLLECTION_SUBTYPE]
287 | classFile.write('\n\t\t\tlet temp_' + propertyName + ' : Dictionary' + ' = typeCast(valuesDict["' + propertyName + '"])!')
288 | else:
289 | classFile.write('\n\t\t\tlet temp_' + propertyName + ' : ' + propertyType + ' = typeCast(valuesDict["' + propertyName + '"])!')
290 |
291 |
292 | def append_failable_initializer_typecasting(classFile, mappingPlist):
293 | for propertyName in mappingPlist.keys():
294 | if MAPPING_KEY_NONOPTIONAL not in mappingPlist[propertyName].keys():
295 | append_failable_typecast_unwrap_statement(classFile, propertyName)
296 | else:
297 | if mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] != 'true':
298 | append_failable_typecast_unwrap_statement(classFile, propertyName)
299 |
300 |
301 | def append_failable_typecast_unwrap_statement(classFile, propertyName):
302 | classFile.write('\n\t\t\tif let unwrapped_' + propertyName + ' : Any = valuesDict["' + propertyName + '"] {\n\t\t\t\t' + propertyName + ' = typeCast(unwrapped_' + propertyName + ')\n\t\t\t}\n')
303 |
304 | def append_failed_initialiser_property(classfile, propertyname, datatype, optional, isFirstLine):
305 | if datatype not in NATIVE_PROPERTY_TYPES:
306 | classfile.write('{}_'.format('' if isFirstLine else ',\n\t\t\t\t ') + propertyname + ' : ' + datatype + '(Dictionary())!{}'.format('?' if optional else ''))
307 | else:
308 | classfile.write('{}_'.format('' if isFirstLine else ',\n\t\t\t\t ') + propertyname + ' : ' + datatype + '(){}'.format('?' if optional else ''))
309 |
310 | def append_array_failed_initialiser_property(classfile, propertyname, datatype, collectionSubtype, optional, isFirstLine):
311 | classfile.write('{}_'.format('' if isFirstLine else ',\n\t\t\t\t ') + propertyname + ' : [' + collectionSubtype + '](){}'.format('?' if optional else ''))
312 |
313 | def append_dictionary_failed_initialiser_property(classfile, propertyname, datatype, collectionSubtype, optional, isFirstLine):
314 | classfile.write( '{}_'.format('' if isFirstLine else ',\n\t\t\t\t ') + propertyname + ' : Dictionary(){}'.format('?' if optional else ''))
315 |
316 |
317 | '''
318 | Create External US2Mapper Inherited File
319 | '''
320 | def generate_internal_instantiator_file(mappingPlist, output_directory):
321 | filename = output_directory + 'Internal/US2Instantiator.swift'
322 |
323 | if not os.path.exists(os.path.dirname(filename)):
324 | os.makedirs(os.path.dirname(filename))
325 |
326 | outputfile = open(filename, "wba")
327 |
328 | outputfile.write(STRING_FILE_INTRO + STRING_IMPORT_FOUNDATION + STRING_USMAPPER_IMPORT)
329 |
330 | classnames = []
331 |
332 | for mapping in mappingPlist:
333 | filename = mapping[mapping.rindex('/',0,-1)+1:-1] if mapping.endswith('/') else mapping[mapping.rindex('/')+1:]
334 | classname = filename.split('.', 1 )[0]
335 | classnames.append(classname)
336 |
337 | outputfile.write('enum US2MapperClassEnum: String {')
338 |
339 | for classname in classnames:
340 | outputfile.write('\n\tcase _' + classname + ' \t= "'+ classname + '"' )
341 |
342 | outputfile.write('\n\tcase _None\t\t\t\t= "None"')
343 | outputfile.write('\n\n\tfunc createObject(data : Dictionary) -> AnyObject? {\n\t\tswitch self {')
344 |
345 | for classname in classnames:
346 | outputfile.write('\n\t\tcase ._' + classname + ':\n\t\t\treturn '+ classname + '(data)' )
347 |
348 | outputfile.write('\n\t\tcase ._None:\n\t\t\treturn nil' )
349 |
350 | outputfile.write('\n\t\t}\n\t}\n}\n\n')
351 |
352 | append_mapper_method_definitions(outputfile, mappingPlist)
353 |
354 | outputfile.write('\n\nclass US2Instantiator : US2InstantiatorProtocol {\n\n\tstatic let sharedInstance : US2Instantiator = US2Instantiator()\n\n\tfunc newInstance(ofType classname : String, withValue data : Dictionary) -> AnyObject? {\n\t\treturn US2MapperClassEnum(rawValue: classname)?.createObject(data)\n\t}\n\n' )
355 |
356 | outputfile.write('\tfunc transformerFromString(classString: String) -> US2TransformerProtocol? {\n\t\treturn US2TransformerEnum(rawValue: classString)!.transformer()\n\t}\n}')
357 | outputfile.close();
358 |
359 |
360 | def append_mapper_method_definitions(classfile, mappinglist):
361 | distinctMapperClassDefinitions = []
362 |
363 | for mappingPath in mappinglist:
364 | mappingPlist = plistlib.readPlist(mappingPath)
365 | mappingKeys = mappingPlist.keys()
366 |
367 | for propertyName in mappingKeys:
368 | if MAPPING_KEY_TRANSFORMER in mappingPlist[propertyName].keys():
369 | mapperClass = mappingPlist[propertyName][MAPPING_KEY_TRANSFORMER]
370 | if mapperClass not in distinctMapperClassDefinitions:
371 | distinctMapperClassDefinitions.append(mapperClass)
372 |
373 | classfile.write('enum US2TransformerEnum: String {')
374 | for mapperClass in distinctMapperClassDefinitions:
375 | classfile.write('\n\tcase _' + mapperClass + ' = "'+ mapperClass + '"' )
376 |
377 | classfile.write('\n\tcase _None = "None"')
378 | classfile.write('\n\n\tfunc transformer() -> US2TransformerProtocol? {\n\t\tswitch self {')
379 |
380 | for mapperClass in distinctMapperClassDefinitions:
381 | classfile.write('\n\t\tcase ._' + mapperClass + ':\n\t\t\treturn ' + mapperClass + '()\n' )
382 |
383 | classfile.write('\n\t\tcase ._None:\n\t\t\treturn nil' )
384 |
385 | classfile.write('\t\t}\n\t} \n}')
386 |
387 |
388 | '''
389 | Create Mapping for Instantiated Class
390 | '''
391 |
392 | '''
393 | Append MapDictionary Setter
394 | '''
395 | def append_map_dictionary_setter(classFile, mappingPlist):
396 | classFile.write(STRING_MAP_DICT_START)
397 | append_map_dictionary_non_optional_typecasting(classFile, mappingPlist)
398 |
399 | classFile.write(' \t\t} \n\t}')
400 |
401 | def append_map_dictionary_non_optional_typecasting(classFile, mappingPlist):
402 | for propertyName in mappingPlist.keys():
403 | if MAPPING_KEY_NONOPTIONAL not in mappingPlist[propertyName].keys():
404 | append_failable_typecast_unwrap_statement(classFile, propertyName)
405 | else:
406 | if mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] != 'true':
407 | append_failable_typecast_unwrap_statement(classFile, propertyName)
408 | else:
409 | append_optional_typecast_unwrap_statement(classFile, propertyName)
410 |
411 | def append_optional_typecast_unwrap_statement(classFile, propertyName):
412 | classFile.write('\n\t\t\tif let unwrapped_' + propertyName + ' : Any = valuesDict["' + propertyName + '"] {\n\t\t\t\t' + propertyName + ' = typeCast(unwrapped_' + propertyName + ')!\n\t\t\t}\n')
413 |
414 |
415 | '''
416 | Validation and System Checks
417 | '''
418 | def validate_class_mapping_configuration(classname, mappingPlist):
419 | for propertyName in mappingPlist.keys():
420 | if MAPPING_KEY_TYPE not in mappingPlist[propertyName].keys():
421 | if MAPPING_KEY_TRANSFORMER not in mappingPlist[propertyName].keys():
422 | throw_missing_type_error(classname, MAPPING_KEY_TYPE, mappingPlist[propertyName])
423 |
424 | if MAPPING_KEY_KEY not in mappingPlist[propertyName].keys():
425 | if MAPPING_KEY_TRANSFORMER not in mappingPlist[propertyName].keys():
426 | throw_missing_json_key_error(classname, MAPPING_KEY_KEY, mappingPlist[propertyName])
427 |
428 | if MAPPING_KEY_KEY in mappingPlist[propertyName].keys():
429 | if MAPPING_KEY_TRANSFORMER in mappingPlist[propertyName].keys():
430 | propertyType = mappingPlist[propertyName][MAPPING_KEY_TYPE]
431 | if xcode_version() == 6.0 and propertyType not in NATIVE_PROPERTY_TYPES:
432 | if MAPPING_KEY_NONOPTIONAL in mappingPlist[propertyName].keys():
433 | if mappingPlist[propertyName][MAPPING_KEY_NONOPTIONAL] == 'true':
434 | throw_missing_nonoptional_error(classname, MAPPING_KEY_KEY, mappingPlist[propertyName])
435 |
436 |
437 | def print_default_error_header(classname, mapping):
438 | print "\n\nUS2Mapper Error: Invalid Configuration (" + classname + ".plist)\n\n"
439 | print mapping
440 | print "\n"
441 |
442 | def throw_missing_type_error(classname, propertykey, mapping):
443 | print_default_error_header(classname, mapping)
444 | print "The mapping configuration for the " + propertykey + " property is missing the type configuration.\nAll properties must specify a 'type' value.\n\n\n\n"
445 | raise Exception('Invalid Configuration')
446 |
447 | def throw_missing_nonoptional_error(classname, propertykey, mapping):
448 | print_default_error_header(classname, mapping)
449 | print "The mapping configuration for the " + propertykey + " cannot be performed. Transformed properties have to be optional when not defined as a native datatype (String, Int, Float, Double, Bool, Array, Dictionary).\n\n\n"
450 | raise Exception('Invalid Configuration')
451 |
452 | def throw_missing_json_key_error(classname, propertykey, mapping):
453 | print_default_error_header(classname, mapping)
454 | print "The mapping configuration for the " + propertykey + " property is missing the key configuration.\nAll properties must specify a 'key' value to map against value in a dictionary.\n\n"
455 | raise Exception('Invalid Configuration')
456 |
457 |
458 | def xcode_version():
459 | status, xcodeVersionString = commands.getstatusoutput("xcodebuild -version")
460 | if xcodeVersionString.find("Xcode 7.") != -1:
461 | return 7.0
462 | else:
463 | return 6.0
464 |
465 |
466 | def main(argv):
467 |
468 | try:
469 | opts, args = getopt.getopt(argv,"hv:i:o:",["version=", "mapdir=", "classdir="])
470 | except getopt.GetoptError:
471 | print 'test.py -v -i -o '
472 | sys.exit(2)
473 | for opt, arg in opts:
474 | if opt == '-h':
475 | print 'test.py -v -i -o '
476 | sys.exit()
477 | elif opt in ("-v", "--version"):
478 | version = arg
479 | elif opt in ("-i", "--mapdir"):
480 | mapdir = arg
481 | elif opt in ("-o", "--classdir"):
482 | classdir = arg
483 |
484 | mappinglist = glob.glob(mapdir + "*.plist")
485 | generate_model(mappinglist, classdir, version)
486 |
487 | if __name__ == "__main__":
488 | main(sys.argv[1:])
--------------------------------------------------------------------------------