├── .gitignore
├── .swift-version
├── .swiftlint.yml
├── .travis.yml
├── Assets
├── data_model_kit_200.png
└── data_model_kit_full.png
├── Cartfile
├── DataModelKit.podspec
├── LICENSE
├── Package.resolved
├── Package.swift
├── README.md
├── Scripts
├── generate_docs.sh
├── launch_tests.sh
└── publish_cocoapods.sh
├── Sources
└── DataModelKit
│ ├── Attribute.swift
│ ├── AttributeType.swift
│ ├── DataModel.swift
│ ├── DataModelError.swift
│ ├── DataModelKit.swift
│ ├── Entity.swift
│ ├── Relationship.swift
│ └── UserInfo.swift
├── Tests
├── DataModelKitTests
│ └── DataModelKitTests.swift
├── LinuxMain.swift
└── Ressources
│ └── Sample.xcdatamodel
│ └── contents
└── logo.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData/
8 |
9 | ## Various settings
10 | *.pbxuser
11 | !default.pbxuser
12 | *.mode1v3
13 | !default.mode1v3
14 | *.mode2v3
15 | !default.mode2v3
16 | *.perspectivev3
17 | !default.perspectivev3
18 | xcuserdata/
19 |
20 | ## Other
21 | *.moved-aside
22 | *.xccheckout
23 | *.xcscmblueprint
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 | *.ipa
28 | *.dSYM.zip
29 | *.dSYM
30 |
31 | ## Playgrounds
32 | timeline.xctimeline
33 | playground.xcworkspace
34 |
35 | # Swift Package Manager
36 | #
37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
38 | # Packages/
39 | # Package.pins
40 | .build/
41 |
42 | # CocoaPods
43 | #
44 | # We recommend against adding the Pods directory to your .gitignore. However
45 | # you should judge for yourself, the pros and cons are mentioned at:
46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
47 | #
48 | # Pods/
49 |
50 | # Carthage
51 | #
52 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
53 | # Carthage/Checkouts
54 |
55 | Carthage/Build
56 |
57 | # fastlane
58 | #
59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
60 | # screenshots whenever they are needed.
61 | # For more information about the recommended setup visit:
62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
63 |
64 | fastlane/report.xml
65 | fastlane/Preview.html
66 | fastlane/screenshots
67 | fastlane/test_output
68 |
--------------------------------------------------------------------------------
/.swift-version:
--------------------------------------------------------------------------------
1 | 4.0
2 |
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | included: # paths to include during linting. `--path` is ignored if present.
2 | - Sources
3 | excluded: # paths to ignore during linting. Takes precedence over `included`.
4 | - .build
5 | - .git
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: swift
2 | osx_image: xcode9
3 |
4 | script:
5 | - set -o pipefail
6 | - xcodebuild -version
7 | - xcodebuild -showsdks
8 | - sh Scripts/launch_tests.sh
9 | after_success:
10 | - bash <(curl -s https://codecov.io/bash)
11 |
--------------------------------------------------------------------------------
/Assets/data_model_kit_200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PoissonBallon/DataModelKit/574dbfc730323b200a0b1d4b4e11e10597fec397/Assets/data_model_kit_200.png
--------------------------------------------------------------------------------
/Assets/data_model_kit_full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PoissonBallon/DataModelKit/574dbfc730323b200a0b1d4b4e11e10597fec397/Assets/data_model_kit_full.png
--------------------------------------------------------------------------------
/Cartfile:
--------------------------------------------------------------------------------
1 | github "drmohundro/SWXMLHash" == "4.2.5"
2 | github "nvzqz/FileKit" == 5.0.0
3 |
--------------------------------------------------------------------------------
/DataModelKit.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # Be sure to run `pod lib lint EasyRealm.podspec' to ensure this is a
3 | # valid spec before submitting.
4 | #
5 | # Any lines starting with a # are optional, but their use is encouraged
6 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
7 | #
8 |
9 | Pod::Spec.new do |s|
10 | s.name = 'DataModelKit'
11 | s.version = '1.1.0'
12 | s.summary = 'DataModelKit is a simple and light framework for read and parse .xcdatamodel'
13 |
14 | # This description is used to generate tags and improve search results.
15 | # * Think: What does it do? Why did you write it? What is the focus?
16 | # * Try to keep it short, snappy and to the point.
17 | # * Write the description between the DESC delimiters below.
18 | # * Finally, don't worry about the indent, CocoaPods strips it!
19 |
20 | s.description = <<-DESC
21 | DataModelKit is a simple and light framework for parse and read *.xcdatamodel files. It provides an API for navigate and explore DataModel
22 | DESC
23 |
24 | s.homepage = 'https://github.com/PoissonBallon/DataModelKit'
25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
26 | s.license = { type: 'MIT', file: 'LICENSE' }
27 | s.author = { 'Allan Vialatte' => 'allan.vialatte@icloud.com' }
28 | s.source = { git: 'https://github.com/PoissonBallon/DataModelKit.git', tag: s.version.to_s }
29 | s.social_media_url = 'https://twitter.com/poissonballon'
30 | s.ios.deployment_target = '10.0'
31 | s.osx.deployment_target = '10.11'
32 | s.tvos.deployment_target = '10.0'
33 | s.watchos.deployment_target = '3.0'
34 | s.ios.deployment_target = '9.0'
35 | s.source_files = 'Sources/**/*'
36 | s.dependency 'SWXMLHash', '4.2.5'
37 | s.dependency 'FileKit', '5.0.0'
38 | end
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Vialatte Allan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "FileKit",
6 | "repositoryURL": "https://github.com/nvzqz/FileKit.git",
7 | "state": {
8 | "branch": null,
9 | "revision": "93505a1ad04b4a2de01abd751ace4f05c6db16a5",
10 | "version": "5.0.0"
11 | }
12 | },
13 | {
14 | "package": "SWXMLHash",
15 | "repositoryURL": "https://github.com/drmohundro/SWXMLHash.git",
16 | "state": {
17 | "branch": null,
18 | "revision": "12496b370363034ccc919e1d72a99b9970b4941e",
19 | "version": "4.2.5"
20 | }
21 | }
22 | ]
23 | },
24 | "version": 1
25 | }
26 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:4.0
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "DataModelKit",
8 | products: [
9 | .library(name: "DataModelKit", targets: ["DataModelKit"]),
10 | ],
11 | dependencies: [
12 | .package(url:"https://github.com/drmohundro/SWXMLHash.git", from: "4.2.5"),
13 | .package(url:"https://github.com/nvzqz/FileKit.git", from: "5.0.0")
14 | ],
15 | targets: [
16 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
17 | // Targets can depend on other targets in this package, and on products in packages which this package depends on.
18 | .target(name: "DataModelKit", dependencies: ["FileKit","SWXMLHash"]),
19 | .testTarget(name: "DataModelKitTests", dependencies: ["DataModelKit"]),
20 | ]
21 | )
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DataModelKit
6 |
7 |
8 |
9 |
10 | [](https://cocoapods.org/pods/DataModelKit)
11 | [](https://github.com/Carthage/Carthage)
12 | [](http://cocoapods.org/pods/DataModelKit)
13 | [](https://travis-ci.org/PoissonBallon/DataModelKit)
14 | [](https://developer.apple.com/swift/)
15 | [](https://codecov.io/gh/PoissonBallon/DataModelKit)
16 | [](http://cocoapods.org/pods/DataModelKit)
17 |
18 |
19 | DataModelKit is a simple and light framework to parse and read __*.xcdatamodel__ files. It provides an API to navigate and explore __DataModel__
20 |
21 | It's used in DataModelGen tools. _(available soon)_
22 |
23 | ## Usage
24 |
25 | ### Init a DataModel Object
26 |
27 | ```swift
28 | import DataModelKit
29 |
30 | static let path = "Project/Ressources/Sample.xcdatamodel"
31 | let model = try? DataModel(with: DataModelKitTests.pathTest)
32 |
33 | print(model.entities)
34 | ```
35 |
36 | ## Installation
37 |
38 | EasyRealm is available through [CocoaPods](http://cocoapods.org), [Carthage](https://github.com/Carthage/Carthage) and [SPM](https://github.com/apple/swift-package-manager).
39 |
40 | #### CocoaPods
41 | ```ruby
42 | use_frameworks!
43 |
44 | pod "DataModelKit"
45 | ```
46 |
47 | #### Carthage
48 | ```ruby
49 |
50 | github 'PoissonBallon/DataModelKit'
51 | ```
52 |
53 | #### SPM
54 | ```swift
55 | dependencies: [
56 | .package(url: "https://github.com/PoissonBallon/DataModelKit.git", .upToNextMinor(from:"1.0.0"))
57 | ],
58 | ```
59 |
60 |
61 | ## API
62 |
63 | DataModelKit provide somes structs with attribute to exploite your DataModel
64 |
65 | #### DataModel
66 | It is the root object of your DataModel
67 |
68 | ```swift
69 |
70 | public struct DataModel {
71 | public let path: Struct /// Path of the original file.xcdatamodel
72 | public let entities: [Entity] /// Parsed model's entities
73 | public let documentVersion: String /// Version of file.xcdatamodel
74 | public let systemVersion: String /// System version of file.xcdatamodel
75 | public let minimumToolsVersion: String /// Minimum tools version of file.xcdatamodel
76 | public let lastSavedToolsVersion: String /// Last saved tools version of file.xcdatamodel
77 | }
78 | ```
79 |
80 | #### Entity
81 |
82 | ```swift
83 | public struct Entity {
84 | public let name: String ///
85 | public let userInfos: [UserInfo]
86 | public let attributes: [Attribute]
87 | public let relationships: [Relationship]
88 | }
89 | ```
90 |
91 | #### Relationship
92 |
93 | ```swift
94 | public struct Relationship {
95 | public let name: String
96 | public let destination: String
97 | public let inverse: String?
98 | public let userInfo: [UserInfo]
99 | public let toMany: Bool
100 | public let toOne: Bool
101 | public let optional: Bool
102 | public let syncable: Bool
103 | public let ordered: Bool
104 | }
105 |
106 | ```
107 |
108 | #### Attribute
109 | ```swift
110 | public struct Attribute {
111 | public let name: String
112 | public let optional: Bool
113 | public let indexed: Bool
114 | public let defaultValue: String?
115 | public let type: String
116 | public let userInfos: [UserInfo]
117 | }
118 | ```
119 |
120 | ## Author
121 |
122 | * PoissonBallon [@poissonballon](https://twitter.com/poissonballon)
123 |
124 | ## License
125 |
126 | DataModelKit is available under the MIT license. See the LICENSE file for more info.
127 |
128 | ## Other
129 |
130 | * Thanks to [Adrien Groleas](https://adriengroleas.fr) for logo
131 | * Thanks to [@trpl](https://github.com/trpl) for text review
132 |
--------------------------------------------------------------------------------
/Scripts/generate_docs.sh:
--------------------------------------------------------------------------------
1 | swift build
2 | sourcekitten doc --spm-module DataModelKit > datamodelkit.json
3 | jazzy \
4 | --clean \
5 | --sourcekitten-sourcefile datamodelkit.json \
6 | --author Allan Vialatte \
7 | --author_url https://github.com/PoissonBallon \
8 | --github_url https://github.com/PoissonBallon/DataModelKit \
9 | --module DataModelKit \
10 |
--------------------------------------------------------------------------------
/Scripts/launch_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | swift package generate-xcodeproj --enable-code-coverage
4 | dataModelPath=`cd Tests/Ressources/Sample.xcdatamodel;pwd`;
5 | echo "$dataModelPath"
6 | DATAMODEL_TEST_PATH=$dataModelPath xcodebuild -scheme DataModelKit-Package -enableCodeCoverage YES test | xcpretty
7 |
--------------------------------------------------------------------------------
/Scripts/publish_cocoapods.sh:
--------------------------------------------------------------------------------
1 | pod lib lint --verbose --allow-warnings
2 | pod trunk push DataModelKit.podspec --allow-warnings
3 |
--------------------------------------------------------------------------------
/Sources/DataModelKit/Attribute.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Attribute.swift
3 | // DataModelKit
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Copyright (c) 2017 Vialatte Allan
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 | //
27 |
28 | import Foundation
29 | import SWXMLHash
30 |
31 | public struct Attribute {
32 | public let name: String
33 | public let optional: Bool
34 | public let indexed: Bool
35 | public let defaultValue: String?
36 | public let type: AttributeType
37 | public let userInfos: [UserInfo]
38 | }
39 |
40 | extension Attribute {
41 |
42 | public init(with node: XMLIndexer) throws {
43 | guard let name = node.element?.attribute(by: "name")?.text else {
44 | throw DataModelError.parserAttributeNameError
45 | }
46 | guard let tmp = node.element?.attribute(by: "attributeType")?.text, let type = AttributeType(rawValue: tmp) else {
47 | throw DataModelError.parserAttributeTypeError
48 | }
49 |
50 | self.name = name
51 | self.type = type
52 | self.optional = (node.element?.attribute(by: "optional")?.text == "YES") ? true : false
53 | self.indexed = (node.element?.attribute(by: "indexed")?.text == "YES") ? true : false
54 | self.defaultValue = node.element?.attribute(by: "defaultValueString")?.text
55 | self.userInfos = node["userInfo"].children.flatMap { try? UserInfo.init(with: $0) }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Sources/DataModelKit/AttributeType.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | // DataModelKitPackageDescription
4 | //
5 | // Created by Allan Vialatte on 18/11/2017.
6 | //
7 |
8 | import Foundation
9 |
10 | public enum AttributeType: String {
11 | case undefined = "Undefined"
12 | case integer16 = "Integer 16"
13 | case integer32 = "Integer 32"
14 | case integer64 = "Integer 64"
15 | case decimal = "Decimal"
16 | case double = "Double"
17 | case float = "Float"
18 | case string = "String"
19 | case boolean = "Boolean"
20 | case date = "Date"
21 | case binaryData = "BinaryData"
22 | case uuid = "UUID"
23 | case uri = "URI"
24 | case transformable = "Transformable"
25 | }
26 |
--------------------------------------------------------------------------------
/Sources/DataModelKit/DataModel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataModel.swift
3 | // DataModelKit
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Copyright (c) 2017 Vialatte Allan
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 | //
27 |
28 | import Foundation
29 | import FileKit
30 | import SWXMLHash
31 |
32 | /// DataModel
33 | public struct DataModel {
34 | private let root: XMLIndexer
35 |
36 | public let path: String /// Path of the original file.xcdatamodel
37 | public let entities: [Entity] /// Parsed model's entities
38 | public let documentVersion: String /// Version of file.xcdatamodel
39 | public let systemVersion: String /// System version of file.xcdatamodel
40 | public let minimumToolsVersion: String /// Minimum tools version of file.xcdatamodel
41 | public let lastSavedToolsVersion: String /// Last saved tools version of file.xcdatamodel
42 | }
43 |
44 | extension DataModel {
45 |
46 | /// Parse and init DataModel
47 | ///
48 | /// - Parameter path: Take the path of an file.xcdatamodel
49 | /// - Throws: throw different error if needed
50 | public init(with path: String) throws {
51 |
52 | let resolvedPath = Path(path).resolved
53 | let file = File.init(path: resolvedPath + "contents")
54 |
55 | guard resolvedPath.pathExtension == DataModelKit.dataModelExtension else {
56 | throw DataModelError.targetIsNotAnXcdataModel
57 | }
58 | guard file.exists else {
59 | throw DataModelError.targetHaveNotContent
60 | }
61 | guard let data = try? file.read() else {
62 | throw DataModelError.targetIsNotReadable
63 | }
64 |
65 | self.path = resolvedPath.description
66 | self.root = SWXMLHash.parse(data)
67 | self.documentVersion = self.root["model"].element?.attribute(by: "documentVersion")?.text ?? ""
68 | self.systemVersion = self.root["model"].element?.attribute(by: "systemVersion")?.text ?? ""
69 | self.minimumToolsVersion = self.root["model"].element?.attribute(by: "minimumToolsVersion")?.text ?? ""
70 | self.lastSavedToolsVersion = self.root["model"].element?.attribute(by: "lastSavedToolsVersion")?.text ?? ""
71 | self.entities = self.root["model"]["entity"].all.flatMap { try? Entity(with: $0) }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Sources/DataModelKit/DataModelError.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataModelError.swift
3 | // DataModelKit
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Copyright (c) 2017 Vialatte Allan
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 | //
27 |
28 | import Foundation
29 |
30 | public enum DataModelError: Error {
31 |
32 | // MARK: Target Reader Error
33 | case targetIsNotAnXcdataModel
34 | case targetHaveNotContent
35 | case targetIsNotReadable
36 |
37 | // MARK: Parser Entity Error
38 | case parserEntityNameError
39 |
40 | // MARK: Parser Attribute Error
41 | case parserAttributeNameError
42 | case parserAttributeTypeError
43 |
44 | // MARK: Parser UserInfo Error
45 | case parserUserInfoKeyError
46 | case parserUserInfoValueError
47 |
48 | // MARK: Parser Relationship Error
49 | case parserRelationshipNameError
50 | case parserRelationshipInverseError
51 | }
52 |
--------------------------------------------------------------------------------
/Sources/DataModelKit/DataModelKit.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataModelKit.swift
3 | // DataModelKit
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Copyright (c) 2017 Vialatte Allan
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 | //
27 |
28 | public struct DataModelKit {
29 | public static let dataModelExtension = "xcdatamodel"
30 | }
31 |
--------------------------------------------------------------------------------
/Sources/DataModelKit/Entity.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DataModelEntity.swift
3 | // DataModelKit
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Copyright (c) 2017 Vialatte Allan
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 | //
27 |
28 | import Foundation
29 | import SWXMLHash
30 |
31 | public struct Entity {
32 | public let name: String
33 | public let userInfos: [UserInfo]
34 | public let attributes: [Attribute]
35 | public let relationships: [Relationship]
36 | }
37 |
38 | extension Entity {
39 |
40 | public init(with node: XMLIndexer) throws {
41 | guard let name = node.element?.attribute(by: "name")?.text else {
42 | throw DataModelError.parserEntityNameError
43 | }
44 | self.name = name
45 | self.attributes = node["attribute"].all.flatMap { try? Attribute.init(with: $0) }
46 | self.userInfos = node["userInfo"].children.flatMap { try? UserInfo.init(with: $0) }
47 | self.relationships = node["relationship"].all.flatMap { try? Relationship.init(with: $0) }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Sources/DataModelKit/Relationship.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Relationship.swift
3 | // DataModelKit
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Copyright (c) 2017 Vialatte Allan
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 | //
27 |
28 | import Foundation
29 | import SWXMLHash
30 |
31 | public struct Relationship {
32 | public let name: String
33 | public let destination: String
34 | public let inverse: String?
35 | public let userInfo: [UserInfo]
36 | public let toMany: Bool
37 | public let toOne: Bool
38 | public let optional: Bool
39 | public let syncable: Bool
40 | public let ordered: Bool
41 | }
42 |
43 | extension Relationship {
44 | public init(with node: XMLIndexer) throws {
45 | guard let name = node.element?.attribute(by: "name")?.text else {
46 | throw DataModelError.parserRelationshipNameError
47 | }
48 | guard let destination = node.element?.attribute(by: "destinationEntity")?.text else {
49 | throw DataModelError.parserRelationshipInverseError
50 | }
51 | self.name = name
52 | self.destination = destination
53 | self.inverse = node.element?.attribute(by: "inverseName")?.text
54 | self.userInfo = node["userInfo"].children.flatMap { try? UserInfo.init(with: $0) }
55 | self.toMany = (node.element?.attribute(by: "toMany")?.text == "YES") ? true : false
56 | self.toOne = !self.toMany
57 | self.optional = (node.element?.attribute(by: "optional")?.text == "YES") ? true : false
58 | self.syncable = (node.element?.attribute(by: "syncable")?.text == "YES") ? true : false
59 | self.ordered = (node.element?.attribute(by: "ordered")?.text == "YES") ? true : false
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Sources/DataModelKit/UserInfo.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserInfo.swift
3 | // DataModelKitPackageDescription
4 | //
5 | // The MIT License (MIT)
6 | //
7 | // Copyright (c) 2017 Vialatte Allan
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in
17 | // all copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 | // THE SOFTWARE.
26 | //
27 |
28 | import Foundation
29 | import SWXMLHash
30 |
31 | public struct UserInfo {
32 | public let key: String
33 | public let value: String
34 | }
35 |
36 | extension UserInfo {
37 |
38 | public init(with node: XMLIndexer) throws {
39 | guard let key = node.element?.attribute(by: "key")?.text else {
40 | throw DataModelError.parserUserInfoKeyError
41 | }
42 | guard let value = node.element?.attribute(by: "value")?.text else {
43 | throw DataModelError.parserUserInfoValueError
44 | }
45 |
46 | self.key = key
47 | self.value = value
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Tests/DataModelKitTests/DataModelKitTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import DataModelKit
3 |
4 | class DataModelKitTests: XCTestCase {
5 |
6 | static let pathTest = ProcessInfo.processInfo.environment["DATAMODEL_TEST_PATH"] ?? ""
7 | static let sampleEntitiesCount = 6
8 | static let sampleArticleAttributesCount = 21
9 | static let sampleArticleFlagUserInfoCount = 3
10 | static let sampleArticleRelationhipCount = 2
11 | static let sampleArticleParagraphRelationhipCount = 1
12 |
13 | func testOpen() {
14 | let model = try? DataModel(with: DataModelKitTests.pathTest)
15 | XCTAssertNotNil(model)
16 | XCTAssertEqual(model!.documentVersion, "1.0")
17 | XCTAssertEqual(model!.systemVersion, "16G29")
18 | }
19 |
20 | func testCount() {
21 | let model = try! DataModel(with: DataModelKitTests.pathTest)
22 | XCTAssertEqual(model.entities.count, DataModelKitTests.sampleEntitiesCount)
23 |
24 | let article = model.entities.first { $0.name == "Article" }
25 | XCTAssertNotNil(article)
26 | XCTAssertEqual(article!.attributes.count, DataModelKitTests.sampleArticleAttributesCount)
27 |
28 | let flag = article?.attributes.first { $0.name == "flag" }
29 | XCTAssertNotNil(flag)
30 | XCTAssertEqual(flag!.userInfos.count, DataModelKitTests.sampleArticleFlagUserInfoCount)
31 | }
32 |
33 | func testRelationship() {
34 | let model = try! DataModel(with: DataModelKitTests.pathTest)
35 |
36 | let entitie = model.entities.first { $0.name == "ArticleParagraph" }
37 | guard let paragraph = entitie else { XCTFail();return }
38 | XCTAssertEqual(paragraph.relationships.count, DataModelKitTests.sampleArticleParagraphRelationhipCount)
39 | guard let relationship = paragraph.relationships.first else { XCTFail();return }
40 | XCTAssertEqual(relationship.name, "article")
41 | XCTAssertEqual(relationship.destination, "Article")
42 | XCTAssertEqual(relationship.inverse!, "paragraphs")
43 | XCTAssertEqual(relationship.optional, true)
44 | XCTAssertEqual(relationship.toOne, true)
45 |
46 | let entitieTwo = model.entities.first { $0.name == "Article" }
47 | guard let article = entitieTwo else { XCTFail();return }
48 | XCTAssertEqual(article.relationships.count, DataModelKitTests.sampleArticleRelationhipCount)
49 | let relaOne = article.relationships.first { $0.name == "images" }
50 | guard let images = relaOne else { XCTFail();return }
51 | XCTAssertEqual(images.destination, "ArticleImage")
52 | XCTAssertEqual(images.inverse, nil)
53 | XCTAssertEqual(images.toMany, true)
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import DataModelKitTests
3 |
4 | XCTMain([
5 | testCase(DataModelKitTests.allTests),
6 | ])
7 |
--------------------------------------------------------------------------------
/Tests/Ressources/Sample.xcdatamodel/contents:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/PoissonBallon/DataModelKit/574dbfc730323b200a0b1d4b4e11e10597fec397/logo.png
--------------------------------------------------------------------------------