|
1 | 1 | package com.wowodc.rest.controllers;
|
2 | 2 |
|
| 3 | +import java.text.ParseException; |
| 4 | +import java.text.SimpleDateFormat; |
| 5 | +import java.util.Locale; |
| 6 | + |
3 | 7 | import com.webobjects.appserver.WOActionResults;
|
| 8 | +import com.webobjects.appserver.WORedirect; |
4 | 9 | import com.webobjects.appserver.WORequest;
|
5 | 10 | import com.webobjects.foundation.NSArray;
|
| 11 | +import com.webobjects.foundation.NSTimestamp; |
6 | 12 | import com.wowodc.model.BlogCategory;
|
7 | 13 | import com.wowodc.model.BlogEntry;
|
| 14 | +import com.wowodc.model.DelegatePKHistory; |
8 | 15 | import com.wowodc.model.Person;
|
9 |
| -import com.wowodc.ui.components.BlogEntryShowPage; |
| 16 | +import com.wowodc.model.SyncInfo; |
| 17 | +import com.wowodc.model.enums.SyncInfoStatus; |
| 18 | +import com.wowodc.ui.components.BlogEntryDetailPage; |
| 19 | +import com.wowodc.ui.components.BlogEntryListPage; |
10 | 20 |
|
| 21 | +import er.extensions.appserver.ERXHttpStatusCodes; |
| 22 | +import er.extensions.appserver.ERXResponse; |
11 | 23 | import er.extensions.eof.ERXKeyFilter;
|
12 | 24 | import er.rest.ERXRestContext;
|
| 25 | +import er.rest.format.ERXRestFormat; |
| 26 | +import er.rest.routes.ERXRouteResults; |
| 27 | +import er.rest.routes.ERXRouteUrlUtils; |
13 | 28 |
|
14 | 29 | public class BlogEntryController extends BaseRestController {
|
15 | 30 |
|
| 31 | + public static final SimpleDateFormat formatter = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.ENGLISH); // Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT |
| 32 | + |
16 | 33 | public BlogEntryController(WORequest request) {
|
17 | 34 | super(request);
|
18 | 35 | }
|
@@ -54,24 +71,150 @@ protected ERXKeyFilter filter() {
|
54 | 71 |
|
55 | 72 | return filter;
|
56 | 73 | }
|
| 74 | + |
| 75 | + public String ifNoneMatchHeader() { |
| 76 | + return this.request().headerForKey("If-None-Match"); |
| 77 | + } |
| 78 | + |
| 79 | + public NSTimestamp ifModifiedSinceHeader() { |
| 80 | + String ifModifiedSinceHeader = this.request().headerForKey("If-Modified-Since"); |
| 81 | + if (ifModifiedSinceHeader != null) { |
| 82 | + java.util.Date ifModifiedSince; |
| 83 | + try { |
| 84 | + ifModifiedSince = formatter.parse(ifModifiedSinceHeader); |
| 85 | + return new NSTimestamp(ifModifiedSince); |
| 86 | + } |
| 87 | + catch (ParseException e) { |
| 88 | + return null; |
| 89 | + } |
| 90 | + } |
| 91 | + return null; |
| 92 | + } |
57 | 93 |
|
| 94 | + public SyncInfo syncInfoForETag() { |
| 95 | + return SyncInfo.fetchSyncInfo(editingContext(), SyncInfo.ETAG.eq(ifNoneMatchHeader())); |
| 96 | + } |
| 97 | + |
| 98 | + public SyncInfo syncInfoForLastModified() throws Throwable { |
| 99 | + return SyncInfo.fetchSyncInfo(editingContext(), SyncInfo.LAST_MODIFIED.eq(ifModifiedSinceHeader())); |
| 100 | + } |
| 101 | + |
| 102 | + public WOActionResults responseForNotModified(SyncInfo syncDetails) { |
| 103 | + if (syncDetails.status() == SyncInfoStatus.DELETED) { |
| 104 | + return response(ERXHttpStatusCodes.GONE); |
| 105 | + } else { |
| 106 | + return response(ERXHttpStatusCodes.NOT_MODIFIED); |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + public boolean isDeleted(String delegatedPK) { |
| 111 | + SyncInfo syncDetails = SyncInfo.fetchSyncInfo(editingContext(), SyncInfo.DELEGATED_PRIMARY_KEY_VALUE.eq(delegatedPK)); |
| 112 | + if (syncDetails != null) { |
| 113 | + if (syncDetails.status() == SyncInfoStatus.DELETED) { |
| 114 | + return true; |
| 115 | + } |
| 116 | + } |
| 117 | + return false; |
| 118 | + } |
| 119 | + |
| 120 | + public SyncInfo delegatedPKInHistory(String delegatedPK) { |
| 121 | + NSArray<DelegatePKHistory> histories = DelegatePKHistory.fetchDelegatePKHistories(editingContext(), DelegatePKHistory.DELEGATED_PRIMARY_KEY_VALUE.eq(delegatedPK), null); |
| 122 | + if (histories.count() > 0) { |
| 123 | + return histories.lastObject().syncInfo(); |
| 124 | + } |
| 125 | + return null; |
| 126 | + } |
| 127 | + |
| 128 | + @Override |
58 | 129 | public WOActionResults showAction() throws Throwable {
|
59 |
| - String title = routeObjectForKey("title"); |
60 |
| - if (title == null) { |
61 |
| - return errorResponse(404); |
| 130 | + SyncInfo syncDetails = null; |
| 131 | + BlogEntry post = null; |
| 132 | + String uniqueTitle = routeObjectForKey("uniqueTitle"); |
| 133 | + |
| 134 | + syncDetails = syncInfoForETag(); |
| 135 | + if (syncDetails != null) { |
| 136 | + return responseForNotModified(syncDetails); |
| 137 | + } else { |
| 138 | + syncDetails = syncInfoForLastModified(); |
| 139 | + if (syncDetails != null) { |
| 140 | + return responseForNotModified(syncDetails); |
| 141 | + } else { |
| 142 | + syncDetails = SyncInfo.fetchSyncInfo(editingContext(), SyncInfo.DELEGATED_PRIMARY_KEY_VALUE.eq(uniqueTitle)); |
| 143 | + post = BlogEntry.fetchBlogEntry(editingContext(), BlogEntry.UNIQUE_TITLE.eq(uniqueTitle)); |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + if (post != null) { |
| 148 | + if (isDeleted(post.uniqueTitle())) { |
| 149 | + return response(ERXHttpStatusCodes.GONE); |
| 150 | + } |
| 151 | + } else { |
| 152 | + syncDetails = delegatedPKInHistory(uniqueTitle); |
| 153 | + if (syncDetails != null) { |
| 154 | + post = BlogEntry.fetchBlogEntry(editingContext(), BlogEntry.UNIQUE_TITLE.eq(syncDetails.delegatedPrimaryKeyValue())); |
| 155 | + if (post != null) { |
| 156 | + WORedirect redirect = new WORedirect(this.context()); |
| 157 | + redirect.setUrl(ERXRouteUrlUtils.actionUrlForRecord(this.context(), post, "show", ERXRestFormat.html().name(), null, false, false)); |
| 158 | + } else { |
| 159 | + return errorResponse(ERXHttpStatusCodes.NOT_FOUND); |
| 160 | + } |
| 161 | + } else { |
| 162 | + return errorResponse(ERXHttpStatusCodes.NOT_FOUND); |
| 163 | + } |
62 | 164 | }
|
63 |
| - BlogEntry post = BlogEntry.fetchRequiredBlogEntry(editingContext(), BlogEntry.TITLE_KEY, title); |
| 165 | + |
| 166 | + ERXResponse response = null; |
| 167 | + |
64 | 168 | if (isHTMlFormat()) {
|
65 |
| - BlogEntryShowPage nextPage = (BlogEntryShowPage)pageWithName(BlogEntryShowPage.class); |
| 169 | + BlogEntryDetailPage nextPage = (BlogEntryDetailPage)pageWithName(BlogEntryDetailPage.class); |
66 | 170 | nextPage.setBlogEntry(post);
|
67 |
| - return nextPage; |
| 171 | + nextPage.setSyncDetails(syncDetails); |
| 172 | + response = (ERXResponse)nextPage.generateResponse(); |
| 173 | + } else { |
| 174 | + response = (ERXResponse) response(post, filter()); |
68 | 175 | }
|
69 |
| - return response(post, filter()); |
| 176 | + |
| 177 | + response.setHeader("max-age=300", "Cache-Control"); |
| 178 | + |
| 179 | + if (syncDetails != null) { |
| 180 | + response.setHeader(formatter.format(syncDetails.lastModified()), "Last-Modified"); |
| 181 | + response.setHeader(syncDetails.etag(), "Etag"); |
| 182 | + } |
| 183 | + |
| 184 | + return response; |
70 | 185 | }
|
71 | 186 |
|
72 | 187 | public WOActionResults indexAction() throws Throwable {
|
73 |
| - NSArray<BlogEntry> entries = BlogEntry.fetchAllBlogEntries(editingContext()); |
74 |
| - return response(entries, filter()); |
| 188 | + ERXRouteResults response = null; |
| 189 | + |
| 190 | + NSArray<SyncInfo> syncDetails = SyncInfo.fetchSyncInfos(editingContext(), SyncInfo.TOKEN.like(BlogEntry.ENTITY_NAME + ":*"), SyncInfo.LAST_MODIFIED.ascs()); |
| 191 | + SyncInfo moreRecentSync = syncDetails.lastObject(); |
| 192 | + |
| 193 | + if (moreRecentSync != null) { |
| 194 | + if (moreRecentSync.etag().equals(ifNoneMatchHeader())) { |
| 195 | + return responseForNotModified(moreRecentSync); |
| 196 | + } |
| 197 | + |
| 198 | + if (moreRecentSync.lastModified().equals(ifModifiedSinceHeader())) { |
| 199 | + return responseForNotModified(moreRecentSync); |
| 200 | + } |
| 201 | + } |
| 202 | + |
| 203 | + if (isHTMlFormat()) { |
| 204 | + BlogEntryListPage nextPage = (BlogEntryListPage)pageWithName(BlogEntryListPage.class); |
| 205 | + nextPage.setSyncDetails(moreRecentSync); |
| 206 | + return nextPage; |
| 207 | + } else { |
| 208 | + NSArray<BlogEntry> entries = BlogEntry.fetchAllBlogEntries(editingContext()); |
| 209 | + response = (ERXRouteResults) response(entries, filter()); |
| 210 | + } |
| 211 | + |
| 212 | + if (moreRecentSync != null) { |
| 213 | + response.setHeaderForKey(formatter.format(moreRecentSync.lastModified()), "Last-Modified"); |
| 214 | + response.setHeaderForKey(moreRecentSync.etag(), "Etag"); |
| 215 | + } |
| 216 | + |
| 217 | + return response; |
75 | 218 | }
|
76 | 219 |
|
77 | 220 | public WOActionResults showByTitleAction() throws Throwable {
|
|
0 commit comments