- RSS 2.0
- Atom (RFC 4287) – selected elements, no feed support
- iTunes (Apple Podcast Connect)
- Content (RDF Site Summary 1.0 Module)
- Podlove Simple Chapters
- Podcastindex.org v1 (example feed)
- Google Play
- Feedpress
- Bitlove
- Fyyd
Scheduled:
- Podcastindex.org v2 in #49 (example feed)
- Spotify in #29
- Dublin Core (RFC 5013) in #28 – properties in the
/elements/1.1/
namespace - Media RSS in #30 (example feed)
Feel free to open an issue if Stalla is missing support for a relevant namespace.
Stalla is distributed via Maven Central.
Maven:
<dependency>
<groupId>dev.stalla</groupId>
<artifactId>stalla</artifactId>
<version>1.0.0</version>
</dependency>
Gradle Kotlin DSL:
implementation("dev.stalla:stalla:1.0.0")
To parse an RSS feed, you need to use the PodcastRssParser
object. Parsing an RSS feed is as easy
as picking the overload of parse()
that fits your needs:
val rssFeedFile = File("/my/path/rss.xml")
val podcast = PodcastRssParser.parse(rssFeedFile)
The parse()
function will return a parsed Podcast?
, which may be null
if parsing was unsuccessful. It will also throw an exception if parsing
fails catastrophically (e.g., the source is a File
that doesn't exist).
In Java, all overloads of parse()
are available as static methods.
To write an RSS feed, you need to use the PodcastRssWriter
object. Writing an RSS feed is as easy
as picking the overload of write()
that fits your needs:
val rssFeedFile = File("/my/path/rss.xml")
val podcast: Podcast = // ...
PodcastRssWriter.writeRssFeed(podcast, rssFeedFile)
The write()
function will throw an exception if writing fails for whatever reason.
In Java, all overloads of write()
are available as static methods.
The two central entities in Stalla's entire data model are Podcast
(abstracting the RSS <channel>
)
and Episode
(abstracting an RSS <item>
).
All model types are Kotlin data classes. Their properties are always un-reassignable (val
), and the
constructors have default values for optional fields (null
) and lists (emptyList()
).
val someEpisode: Episode = // ...
val podcast = Podcast(
title = "The Stalla Show",
description = "A show about Stalla development",
link = "https://stalla.dev/podcast",
language = Locale.ENGLISH,
episodes = listOf(firstEpisode)
)
The Java language does not provide named arguments. Some of Stalla's model classes take huge parameter lists. To mitigate this limitation, every model
class provides a static builder()
method that returns a builder instance enabling expressive construction in Java.
Episode someEpisode = // ...
Podcast podcast = Podcast.builder()
.title("The Stalla Show")
.description("A show about Stalla development")
.link("https://stalla.dev/podcast")
.language(Locale.ENGLISH)
.addEpisodeBuilder(firstEpisode)
.build();
Note that builders validate lazily upon calling build()
, i.e., the constructed model instance may be null
if:
- Not all required constructor properties of the backing data class have been initialized in the builder (technical requirement by the type system).
- Not all mandatory information bas been provided with respect to the backing specification (RSS or other XML namespace). For example, a
Podcast
needs at least oneEpisode
(i.e. one<item>
within the<channel>
), so while technically an empty list satisfies the technical requirement (required to be notnull
), it however violates the logical requirement (at least one element).
The supported XML namespaces declare several elements that only accept a finite set of predefined values. In Stalla, these values are usually modeled
via enum classes (e.g., GoogleplayCategory
or
TranscriptType
). However, some elements, like the Categories of the iTunes
namespace, have a more complex structure (i.e., a hierarchy) that cannot be modeled via enums. These types still try to provide an interface that is
close to that of enums for consistent usage. For example, ItunesCategory
exposes all
possible values as members of the companion object (Kotlin) or as static class members (Java).
Note that the instances exposed by MediaType
are not the finite set of possible values, but only
predefined instances for convenience.
All model classes expose a builder()
method as a member of the companion object (Kotlin) or as a static class method (Java). These methods return an
implementation of the respective model classes builder interface. The builder pattern enables
expressive object construction using named attribute initializers, and compensate for the lack of named constructor arguments in the Java language.
All builders expose an applyFrom(model)
method that takes an instance of the builder's model class as argument, and returns the builder instance. The
method applies all values of the provided model to the builder's state. This is therefore a mutating operation. The returned builder instance is the
mutated state of the builder on which the applyFrom
method is called, and not a new instance. The operation does not result in any structural
sharing, e.g., references of lists, etc.
The generic use case of this method is the convenient construction of a new model object based on the properties of an existing model instance:
Episode oldEpisode = // ...
Episode newEpisode = Episode.builder()
.applyFrom(oldEpisode)
.title("The latest episode")
.build();
In Kotlin, you can also use the copy()
method exposed by all data classes to obtain a new model instance with some of its properties mutated.
All enumerated types expose an of(String)
method as a member of the companion object (Kotlin) or as a static class method (Java). This method is a
factory and produces an instance of the type if possible, otherwise null
. In contrast to the enum classes' valueOf()
standard method, of()
is
case-insensitive and also available for non-enum class enumerated types (e.g.,
ItunesCategory
).
Additionally, Stalla has some types that validate a string for certain patterns, e.g. MediaType
models media types as defined by RFC 2046, and
StyledDuration
describes values in several supported time formats (14:02:56
or 5:23
or
33.833
). These types also provide the of()
method as the only means to obtain an instance of the class.
The project uses Dokka to generate its documentation from the KDoc comments in the code. If you want to generate a fresh version of the documentation, use one of the Dokka Gradle tasks:
$ ./gradlew dokkaHtml
$ ./gradlew dokkaJavadoc
$ ./gradlew dokkaGfm
$ ./gradlew dokkaJekyll
Stalla is released under the BSD 3-clause license.