001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.bean.atom; 018 019import static org.apache.juneau.xml.annotation.XmlFormat.*; 020 021import java.util.*; 022 023import org.apache.juneau.annotation.*; 024import org.apache.juneau.xml.annotation.*; 025 026/** 027 * Represents a top-level Atom feed document. 028 * 029 * <p> 030 * An Atom feed is a Web resource that contains metadata and optionally a set of entries. 031 * Feeds are the top-level container element in Atom documents and act as a manifest of metadata 032 * and data associated with a collection of related resources. 033 * 034 * <p> 035 * The feed is the fundamental unit of syndication in Atom and is used to aggregate entries that 036 * share a common purpose, such as a blog, podcast channel, or news source. 037 * 038 * <h5 class='figure'>Schema</h5> 039 * <p class='bschema'> 040 * atomFeed = 041 * element atom:feed { 042 * atomCommonAttributes, 043 * (atomAuthor* 044 * & atomCategory* 045 * & atomContributor* 046 * & atomGenerator? 047 * & atomIcon? 048 * & atomId 049 * & atomLink* 050 * & atomLogo? 051 * & atomRights? 052 * & atomSubtitle? 053 * & atomTitle 054 * & atomUpdated 055 * & extensionElement*), 056 * atomEntry* 057 * } 058 * </p> 059 * 060 * <h5 class='section'>Required Elements:</h5> 061 * <p> 062 * Per RFC 4287, the following elements are required in a feed: 063 * <ul class='spaced-list'> 064 * <li><c>atom:id</c> - A permanent, universally unique identifier for the feed. 065 * <li><c>atom:title</c> - A human-readable title for the feed. 066 * <li><c>atom:updated</c> - The most recent instant in time when the feed was modified. 067 * </ul> 068 * 069 * <h5 class='section'>Recommended Elements:</h5> 070 * <p> 071 * The following elements are recommended but not required: 072 * <ul class='spaced-list'> 073 * <li><c>atom:author</c> - Authors of the feed (required if entries don't have authors). 074 * <li><c>atom:link</c> - Links associated with the feed (should include a "self" link). 075 * </ul> 076 * 077 * <h5 class='section'>Example:</h5> 078 * <p class='bjava'> 079 * <jc>// Create a feed using fluent-style setters</jc> 080 * Feed <jv>feed</jv> = <jk>new</jk> Feed( 081 * <js>"tag:example.org,2024:feed"</js>, 082 * <js>"Example Feed"</js>, 083 * <js>"2024-01-15T12:00:00Z"</js> 084 * ) 085 * .setSubtitle(<js>"A sample Atom feed"</js>) 086 * .setLinks( 087 * <jk>new</jk> Link(<js>"self"</js>, <js>"application/atom+xml"</js>, <js>"http://example.org/feed.atom"</js>), 088 * <jk>new</jk> Link(<js>"alternate"</js>, <js>"text/html"</js>, <js>"http://example.org"</js>) 089 * ) 090 * .setAuthors( 091 * <jk>new</jk> Person(<js>"John Doe"</js>).setEmail(<js>"john@example.org"</js>) 092 * ) 093 * .setEntries( 094 * <jk>new</jk> Entry(<js>"tag:example.org,2024:entry1"</js>, <js>"First Post"</js>, <js>"2024-01-15T12:00:00Z"</js>) 095 * .setSummary(<js>"This is the first post"</js>) 096 * ); 097 * 098 * <jc>// Serialize to ATOM/XML</jc> 099 * String <jv>atomXml</jv> = XmlSerializer.<jsf>DEFAULT_SQ_READABLE</jsf>.serialize(<jv>feed</jv>); 100 * </p> 101 * 102 * <h5 class='section'>Specification:</h5> 103 * <p> 104 * Represents an <c>atomFeed</c> construct in the 105 * <a class="doclink" href="https://tools.ietf.org/html/rfc4287#section-4.1.1">RFC 4287 - Section 4.1.1</a> specification. 106 * 107 * <h5 class='section'>See Also:</h5><ul> 108 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanAtom">juneau-bean-atom</a> 109 * <li class='extlink'><a class="doclink" href="https://tools.ietf.org/html/rfc4287">RFC 4287 - The Atom Syndication Format</a> 110 * </ul> 111 */ 112@Bean(typeName = "feed") 113public class Feed extends CommonEntry { 114 115 // @formatter:off 116 private Generator generator; // atomGenerator? 117 private Icon icon; // atomIcon? 118 private Logo logo; // atomLogo? 119 private Text subtitle; // atomSubtitle? 120 private Entry[] entries; // atomEntry* 121 // @formatter:on 122 123 /** Bean constructor. */ 124 public Feed() {} 125 126 /** 127 * Normal constructor. 128 * 129 * @param id The feed identifier. 130 * @param title The feed title. 131 * @param updated The feed updated timestamp. 132 */ 133 public Feed(Id id, Text title, Calendar updated) { 134 super(id, title, updated); 135 } 136 137 /** 138 * Normal constructor. 139 * 140 * @param id The feed identifier. 141 * @param title The feed title. 142 * @param updated The feed updated timestamp. 143 */ 144 public Feed(String id, String title, String updated) { 145 super(id, title, updated); 146 } 147 148 /** 149 * Bean property getter: <property>entries</property>. 150 * 151 * <p> 152 * Returns the individual entries contained within this feed. 153 * 154 * <p> 155 * Each entry represents a single item in the feed, such as a blog post, news article, 156 * podcast episode, or other discrete piece of content. Entries contain their own metadata 157 * including title, content, links, and timestamps. 158 * 159 * @return The property value, or <jk>null</jk> if it is not set. 160 */ 161 @Xml(format = COLLAPSED) 162 public Entry[] getEntries() { return entries; } 163 164 /** 165 * Bean property getter: <property>generator</property>. 166 * 167 * <p> 168 * Identifies the software agent used to generate the feed. 169 * 170 * <p> 171 * This is useful for debugging and analytics purposes, allowing consumers to identify the 172 * software responsible for producing the feed. 173 * 174 * @return The property value, or <jk>null</jk> if it is not set. 175 */ 176 public Generator getGenerator() { return generator; } 177 178 /** 179 * Bean property getter: <property>icon</property>. 180 * 181 * <p> 182 * Identifies a small image that provides iconic visual identification for the feed. 183 * 184 * <p> 185 * Icons should be square and small (typically 16x16 or similar). The image should have an 186 * aspect ratio of 1 (horizontal) to 1 (vertical). 187 * 188 * @return The property value, or <jk>null</jk> if it is not set. 189 */ 190 public Icon getIcon() { return icon; } 191 192 /** 193 * Bean property getter: <property>logo</property>. 194 * 195 * <p> 196 * Identifies a larger image that provides visual identification for the feed. 197 * 198 * <p> 199 * Logos should be twice as wide as they are tall (aspect ratio of 2:1). 200 * 201 * @return The property value, or <jk>null</jk> if it is not set. 202 */ 203 public Logo getLogo() { return logo; } 204 205 /** 206 * Bean property getter: <property>subtitle</property>. 207 * 208 * <p> 209 * Returns a human-readable description or subtitle for the feed. 210 * 211 * <p> 212 * The subtitle provides additional context about the feed's purpose or content beyond 213 * what is conveyed in the title. 214 * 215 * @return The property value, or <jk>null</jk> if it is not set. 216 */ 217 public Text getSubtitle() { return subtitle; } 218 219 @Override /* Overridden from CommonEntry */ 220 public Feed setAuthors(Person...value) { 221 super.setAuthors(value); 222 return this; 223 } 224 225 @Override /* Overridden from Common */ 226 public Feed setBase(Object value) { 227 super.setBase(value); 228 return this; 229 } 230 231 @Override /* Overridden from CommonEntry */ 232 public Feed setCategories(Category...value) { 233 super.setCategories(value); 234 return this; 235 } 236 237 @Override /* Overridden from CommonEntry */ 238 public Feed setContributors(Person...value) { 239 super.setContributors(value); 240 return this; 241 } 242 243 /** 244 * Bean property setter: <property>entries</property>. 245 * 246 * <p> 247 * Sets the individual entries contained within this feed. 248 * 249 * <h5 class='section'>Example:</h5> 250 * <p class='bjava'> 251 * Feed <jv>feed</jv> = <jk>new</jk> Feed(...) 252 * .setEntries( 253 * <jk>new</jk> Entry( 254 * <js>"tag:example.org,2024:entry1"</js>, 255 * <js>"First Post"</js>, 256 * <js>"2024-01-15T12:00:00Z"</js> 257 * ) 258 * .setContent( 259 * <jk>new</jk> Content(<js>"html"</js>) 260 * .setText(<js>"<p>This is the content</p>"</js>) 261 * ), 262 * <jk>new</jk> Entry( 263 * <js>"tag:example.org,2024:entry2"</js>, 264 * <js>"Second Post"</js>, 265 * <js>"2024-01-16T12:00:00Z"</js> 266 * ) 267 * ); 268 * </p> 269 * 270 * @param value 271 * The new value for this property. 272 * <br>Can be <jk>null</jk> to unset the property. 273 * @return This object. 274 */ 275 public Feed setEntries(Entry...value) { 276 entries = value; 277 return this; 278 } 279 280 /** 281 * Bean property setter: <property>generator</property>. 282 * 283 * <p> 284 * Identifies the software agent used to generate the feed. 285 * 286 * <h5 class='section'>Example:</h5> 287 * <p class='bjava'> 288 * Feed <jv>feed</jv> = <jk>new</jk> Feed(...) 289 * .setGenerator( 290 * <jk>new</jk> Generator(<js>"My Blog Software"</js>) 291 * .setUri(<js>"http://www.example.com/software"</js>) 292 * .setVersion(<js>"2.0"</js>) 293 * ); 294 * </p> 295 * 296 * @param value 297 * The new value for this property. 298 * <br>Can be <jk>null</jk> to unset the property. 299 * @return This object. 300 */ 301 public Feed setGenerator(Generator value) { 302 generator = value; 303 return this; 304 } 305 306 /** 307 * Bean property setter: <property>icon</property>. 308 * 309 * <p> 310 * Identifies a small image that provides iconic visual identification for the feed. 311 * 312 * <h5 class='section'>Example:</h5> 313 * <p class='bjava'> 314 * Feed <jv>feed</jv> = <jk>new</jk> Feed(...) 315 * .setIcon(<jk>new</jk> Icon(<js>"http://example.org/icon.png"</js>)); 316 * </p> 317 * 318 * @param value 319 * The new value for this property. 320 * <br>Can be <jk>null</jk> to unset the property. 321 * @return This object. 322 */ 323 public Feed setIcon(Icon value) { 324 icon = value; 325 return this; 326 } 327 328 @Override /* Overridden from CommonEntry */ 329 public Feed setId(Id value) { 330 super.setId(value); 331 return this; 332 } 333 334 @Override /* Overridden from CommonEntry */ 335 public Feed setId(String value) { 336 super.setId(value); 337 return this; 338 } 339 340 @Override /* Overridden from Common */ 341 public Feed setLang(String value) { 342 super.setLang(value); 343 return this; 344 } 345 346 @Override /* Overridden from CommonEntry */ 347 public Feed setLinks(Link...value) { 348 super.setLinks(value); 349 return this; 350 } 351 352 /** 353 * Bean property setter: <property>logo</property>. 354 * 355 * <p> 356 * Identifies a larger image that provides visual identification for the feed. 357 * 358 * <h5 class='section'>Example:</h5> 359 * <p class='bjava'> 360 * Feed <jv>feed</jv> = <jk>new</jk> Feed(...) 361 * .setLogo(<jk>new</jk> Logo(<js>"http://example.org/logo.png"</js>)); 362 * </p> 363 * 364 * @param value 365 * The new value for this property. 366 * <br>Can be <jk>null</jk> to unset the property. 367 * @return This object. 368 */ 369 public Feed setLogo(Logo value) { 370 logo = value; 371 return this; 372 } 373 374 @Override /* Overridden from CommonEntry */ 375 public Feed setRights(String value) { 376 super.setRights(value); 377 return this; 378 } 379 380 @Override /* Overridden from CommonEntry */ 381 public Feed setRights(Text value) { 382 super.setRights(value); 383 return this; 384 } 385 386 /** 387 * Bean property fluent setter: <property>subtitle</property>. 388 * 389 * <p> 390 * Sets a human-readable description or subtitle for the feed as plain text. 391 * 392 * @param value 393 * The new value for this property. 394 * <br>Can be <jk>null</jk> to unset the property. 395 * @return This object. 396 */ 397 public Feed setSubtitle(String value) { 398 setSubtitle(new Text(value)); 399 return this; 400 } 401 402 /** 403 * Bean property setter: <property>subtitle</property>. 404 * 405 * <p> 406 * Sets a human-readable description or subtitle for the feed. 407 * 408 * <h5 class='section'>Example:</h5> 409 * <p class='bjava'> 410 * Feed <jv>feed</jv> = <jk>new</jk> Feed(...) 411 * .setSubtitle( 412 * <jk>new</jk> Text(<js>"html"</js>) 413 * .setText(<js>"A <em>comprehensive</em> guide to Atom feeds"</js>) 414 * ); 415 * </p> 416 * 417 * @param value 418 * The new value for this property. 419 * <br>Can be <jk>null</jk> to unset the property. 420 * @return This object. 421 */ 422 public Feed setSubtitle(Text value) { 423 subtitle = value; 424 return this; 425 } 426 427 @Override /* Overridden from CommonEntry */ 428 public Feed setTitle(String value) { 429 super.setTitle(value); 430 return this; 431 } 432 433 @Override /* Overridden from CommonEntry */ 434 public Feed setTitle(Text value) { 435 super.setTitle(value); 436 return this; 437 } 438 439 @Override /* Overridden from CommonEntry */ 440 public Feed setUpdated(Calendar value) { 441 super.setUpdated(value); 442 return this; 443 } 444 445 @Override /* Overridden from CommonEntry */ 446 public Feed setUpdated(String value) { 447 super.setUpdated(value); 448 return this; 449 } 450}