Add ArticleID struct.

This commit is contained in:
Brent Simmons 2017-07-10 21:47:27 -07:00
parent c79580b87c
commit 7ce19b0659
4 changed files with 52 additions and 10 deletions

View File

@ -12,9 +12,7 @@ public final class Article: Hashable {
weak var account: Account? weak var account: Account?
public let feedID: String public let articleID: ArticleID
public let articleID: String //Calculated: unique per account
public var uniqueID: String //guid: unique per feed
public var title: String? public var title: String?
public var contentHTML: String? public var contentHTML: String?
public var contentText: String? public var contentText: String?
@ -35,15 +33,14 @@ public final class Article: Hashable {
var feed: Feed? { var feed: Feed? {
get { get {
return account?.existingFeed(with: feedID) return account?.existingFeed(with: articleID.feedID)
} }
} }
init(account: Account, feedID: String, uniqueID: String, title: String?, contentHTML: String?, contentText: String?, url: String?, externalURL: String?, summary: String?, imageURL: String?, bannerImageURL: String?, datePublished: Date?, dateModified: Date?, authors: [Author]?, tags: Set<String>?, attachments: [Attachment]?, accountInfo: AccountInfo?) { init(account: Account, feedID: String, uniqueID: String, title: String?, contentHTML: String?, contentText: String?, url: String?, externalURL: String?, summary: String?, imageURL: String?, bannerImageURL: String?, datePublished: Date?, dateModified: Date?, authors: [Author]?, tags: Set<String>?, attachments: [Attachment]?, accountInfo: AccountInfo?) {
self.account = account self.account = account
self.feedID = feedID self.articleID = ArticleID(feedID: feedID, uniqueID: uniqueID)
self.uniqueID = uniqueID
self.title = title self.title = title
self.contentHTML = contentHTML self.contentHTML = contentHTML
self.contentText = contentText self.contentText = contentText
@ -59,8 +56,7 @@ public final class Article: Hashable {
self.attachments = attachments self.attachments = attachments
self.accountInfo = accountInfo self.accountInfo = accountInfo
self.articleID = "\(feedID) \(uniqueID)" self.hashValue = account.hashValue ^ self.articleID.hashValue
self.hashValue = account.hashValue + feedID.hashValue + uniqueID.hashValue
} }
public class func ==(lhs: Article, rhs: Article) -> Bool { public class func ==(lhs: Article, rhs: Article) -> Bool {

View File

@ -0,0 +1,39 @@
//
// ArticleID.swift
// Data
//
// Created by Brent Simmons on 7/10/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import Foundation
// Any given articles unique ID is unique only for the feed it appears in.
// We cant rely on feed authors to produce globally unique identifiers.
// So ArticleID includes the feedID as well as the uniqueID.
//
// While we could use a compound primary key in the database (feedID, articleID),
// that complicates things more than a bit. So ArticleID.stringValue provides
// a single value that can be used as a primary key.
public struct ArticleID: Hashable {
public let feedID: String
public let uniqueID: String
public let stringValue: String // Stored in database
public let hashValue: Int
public init(feedID: String, uniqueID: String) {
self.feedID = feedID
self.uniqueID = uniqueID
self.stringValue = "\(feedID) \(uniqueID)"
self.hashValue = stringValue.hashValue
}
public static func ==(lhs: ArticleID, rhs: ArticleID) -> Bool {
return lhs.hashValue == rhs.hashValue && lhs.feedID == rhs.uniqueID && lhs.feedID == rhs.feedID
}
}

View File

@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
843079FA1F0AB57F00B4B7F7 /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844BEEA31F0AB512004AB7CD /* RSCore.framework */; }; 843079FA1F0AB57F00B4B7F7 /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844BEEA31F0AB512004AB7CD /* RSCore.framework */; };
843A08BA1F148A4400D9C438 /* ArticleID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843A08B91F148A4400D9C438 /* ArticleID.swift */; };
844BEE651F0AB3C9004AB7CD /* Data.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844BEE5B1F0AB3C8004AB7CD /* Data.framework */; }; 844BEE651F0AB3C9004AB7CD /* Data.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844BEE5B1F0AB3C8004AB7CD /* Data.framework */; };
844BEE6A1F0AB3C9004AB7CD /* DataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE691F0AB3C9004AB7CD /* DataTests.swift */; }; 844BEE6A1F0AB3C9004AB7CD /* DataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE691F0AB3C9004AB7CD /* DataTests.swift */; };
844BEE791F0AB4B8004AB7CD /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE781F0AB4B8004AB7CD /* Account.swift */; }; 844BEE791F0AB4B8004AB7CD /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE781F0AB4B8004AB7CD /* Account.swift */; };
@ -61,6 +62,7 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
843A08B91F148A4400D9C438 /* ArticleID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleID.swift; sourceTree = "<group>"; };
844BEE5B1F0AB3C8004AB7CD /* Data.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Data.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 844BEE5B1F0AB3C8004AB7CD /* Data.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Data.framework; sourceTree = BUILT_PRODUCTS_DIR; };
844BEE641F0AB3C9004AB7CD /* DataTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DataTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 844BEE641F0AB3C9004AB7CD /* DataTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DataTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
844BEE691F0AB3C9004AB7CD /* DataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTests.swift; sourceTree = "<group>"; }; 844BEE691F0AB3C9004AB7CD /* DataTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTests.swift; sourceTree = "<group>"; };
@ -112,6 +114,7 @@
844BEE781F0AB4B8004AB7CD /* Account.swift */, 844BEE781F0AB4B8004AB7CD /* Account.swift */,
844BEE7A1F0AB4BE004AB7CD /* Folder.swift */, 844BEE7A1F0AB4BE004AB7CD /* Folder.swift */,
844BEE7C1F0AB4C4004AB7CD /* Feed.swift */, 844BEE7C1F0AB4C4004AB7CD /* Feed.swift */,
843A08B91F148A4400D9C438 /* ArticleID.swift */,
844BEE7E1F0AB4CA004AB7CD /* Article.swift */, 844BEE7E1F0AB4CA004AB7CD /* Article.swift */,
844BEE801F0AB4D0004AB7CD /* Author.swift */, 844BEE801F0AB4D0004AB7CD /* Author.swift */,
844BEE821F0AB4D6004AB7CD /* Attachment.swift */, 844BEE821F0AB4D6004AB7CD /* Attachment.swift */,
@ -336,6 +339,7 @@
844BEE9A1F0AB4F8004AB7CD /* DisplayNameProvider.swift in Sources */, 844BEE9A1F0AB4F8004AB7CD /* DisplayNameProvider.swift in Sources */,
844BEE8F1F0AB4EF004AB7CD /* Account+OPMLRepresentable.swift in Sources */, 844BEE8F1F0AB4EF004AB7CD /* Account+OPMLRepresentable.swift in Sources */,
844BEE991F0AB4F8004AB7CD /* Container.swift in Sources */, 844BEE991F0AB4F8004AB7CD /* Container.swift in Sources */,
843A08BA1F148A4400D9C438 /* ArticleID.swift in Sources */,
844BEE7B1F0AB4BE004AB7CD /* Folder.swift in Sources */, 844BEE7B1F0AB4BE004AB7CD /* Folder.swift in Sources */,
844BEE981F0AB4F8004AB7CD /* AccountDelegate.swift in Sources */, 844BEE981F0AB4F8004AB7CD /* AccountDelegate.swift in Sources */,
844BEE831F0AB4D6004AB7CD /* Attachment.swift in Sources */, 844BEE831F0AB4D6004AB7CD /* Attachment.swift in Sources */,

View File

@ -1,4 +1,4 @@
CREATE TABLE if not EXISTS articles (articleID TEXT NOT NULL PRIMARY KEY, feedID TEXT NOT NULL, uniqueID TEXT, title TEXT, contentHTML TEXT, contentText TEXT, url TEXT, externalURL TEXT, summary TEXT, imageURL TEXT, bannerImageURL TEXT, datePublished DATE, dateModified DATE, accountInfo BLOB); CREATE TABLE if not EXISTS articles (articleID TEXT NOT NULL PRIMARY KEY, feedID TEXT NOT NULL, uniqueID TEXT NOT NULL, title TEXT, contentHTML TEXT, contentText TEXT, url TEXT, externalURL TEXT, summary TEXT, imageURL TEXT, bannerImageURL TEXT, datePublished DATE, dateModified DATE, accountInfo BLOB);
CREATE TABLE if not EXISTS statuses (articleID TEXT NOT NULL PRIMARY KEY, read BOOL NOT NULL DEFAULT 0, starred BOOL NOT NULL DEFAULT 0, userDeleted BOOL NOT NULL DEFAULT 0, dateArrived DATE NOT NULL DEFAULT 0, accountInfo BLOB); CREATE TABLE if not EXISTS statuses (articleID TEXT NOT NULL PRIMARY KEY, read BOOL NOT NULL DEFAULT 0, starred BOOL NOT NULL DEFAULT 0, userDeleted BOOL NOT NULL DEFAULT 0, dateArrived DATE NOT NULL DEFAULT 0, accountInfo BLOB);
@ -10,3 +10,6 @@ CREATE TABLE if not EXISTS tags(tagName TEXT NOT NULL, articleID TEXT NOT NULL,
CREATE TABLE if not EXISTS attachments(articleID TEXT NOT NULL, url TEXT NOT NULL, mimeType TEXT, title TEXT, sizeInBytes INTEGER, durationInSeconds INTEGER, PRIMARY KEY(articleID, url)); CREATE TABLE if not EXISTS attachments(articleID TEXT NOT NULL, url TEXT NOT NULL, mimeType TEXT, title TEXT, sizeInBytes INTEGER, durationInSeconds INTEGER, PRIMARY KEY(articleID, url));
CREATE INDEX if not EXISTS feedIndex on articles (feedID); CREATE INDEX if not EXISTS feedIndex on articles (feedID);
CREATE INDEX if not EXISTS tags_tagName_index on tags(tagName COLLATE NOCASE);