Skip to content

Commit

Permalink
Merge pull request #29 from QuickWrite/develop
Browse files Browse the repository at this point in the history
Version 1.0.0
  • Loading branch information
QuickWrite authored Sep 17, 2023
2 parents 73ef170 + 92873f4 commit 5829fb2
Show file tree
Hide file tree
Showing 245 changed files with 6,782 additions and 6,344 deletions.
48 changes: 34 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,33 +43,53 @@ dependencies {
}
```

## Usage
## What is `fluent4j`?
The `fluent4j` library is a Java implementation of [Mozillas Fluent project](https://www.projectfluent.org/) that
intends to be extensible by default.

You could either use the library directly without all of the abstraction and create all of the
objects by yourself:
This means that custom constructs can be added to the basic fluent syntax so that the translation files can be used
for the projects exact needs.

## Usage
So that the translation files can be used the files need to be parsed first:
```java
FluentResource resource = FluentParser.parse("emails = You have { $unreadEmails } unread emails.");
FluentBundle bundle = new ResourceFluentBundle(ULocale.ENGLISH, resource);
ResourceParser resourceParser = ResourceParserBuilder.defaultParser();

FluentArgs arguments = new FluentArguments();
arguments.setNamed("unreadEmails", new NumberLiteral(10));
FluentResource resource = resourceParser.parse(FluentIteratorFactory.fromString("""
test = This is your fluent file
System.out.println(bundle.getMessage("emails", arguments).get());
emails = You have { $unreadEmails } unread emails.
"""));
```

or you could use the builders that the library provides for this:
After you've created a single or multiple Resources you can bundle them in a Bundle with other data for use:
```java
FluentBundle bundle = FluentBundleBuilder.builder(Locale.ENGLISH)
.addResource(resource)
.build();
```

And now you can use the different messages for translation:
```java
FluentBundle bundle = new FluentBundleBuilder(ULocale.ENGLISH, "emails = You have { $unreadEmails } unread emails.")
.build();
System.out.println(bundle.resolveMessage("test", new StringResultBuilder()).get());
```

FluentArgs arguments = new FluentArgsBuilder().set("unreadEmails", 10).build();
```console
This is your fluent file
```

And you can also provide arguments for the messages:
```java
FluentArguments arguments = ArgumentListBuilder.builder()
.add("unreadEmails", 5)
.build();

System.out.println(bundle.getMessage("emails", arguments).get());
System.out.println(bundle.resolveMessage("emails", arguments, new StringResultBuilder()).get());
```

In both cases they would print the message `You have 10 unread emails.`.
```console
You have 5 unread emails.
```

## License
This project is licensed under the permissive [Apache 2.0 license](LICENSE).
20 changes: 20 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.quickwrite</groupId>
<artifactId>fluent4j</artifactId>
<version>0.2.3-alpha</version>
</parent>

<artifactId>api</artifactId>

<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

</project>
28 changes: 28 additions & 0 deletions api/src/main/java/net/quickwrite/fluent4j/ast/FluentFunction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package net.quickwrite.fluent4j.ast;

import net.quickwrite.fluent4j.ast.pattern.ArgumentList;
import net.quickwrite.fluent4j.ast.placeable.FluentPlaceable;
import net.quickwrite.fluent4j.container.FluentScope;

/**
* The FluentFunction interface represents a function.
* Functions provide additional functionality available to the
* localizers for formatting data or providing additional data.
*/
public interface FluentFunction {
/**
* Retrieves the identifier of the function.
*
* @return The identifier of the function
*/
String getIdentifier();

/**
* Evaluates the function with the given scope and argument list.
*
* @param scope The FluentScope used for evaluating
* @param argumentList The ArgumentList containing the arguments passed to the function
* @return A FluentPlaceable representing the evaluated function
*/
FluentPlaceable parseFunction(final FluentScope scope, final ArgumentList argumentList);
}
35 changes: 35 additions & 0 deletions api/src/main/java/net/quickwrite/fluent4j/ast/FluentPattern.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.quickwrite.fluent4j.ast;

import net.quickwrite.fluent4j.container.FluentScope;
import net.quickwrite.fluent4j.exception.FluentPatternException;

/**
* A pattern itself is the base element for the
* message. With that a pattern can be a TextElement
* or a {@link net.quickwrite.fluent4j.ast.placeable.FluentPlaceable}.
*/
public interface FluentPattern extends FluentResolvable {
/**
* Returns the element that this element links to. If the element
* itself for example is a Message Reference the message itself should be returned.
*
* <hr />
*
* If the element contains the necessary information directly
* (like a simple Text Element) this should return itself.
*
* @param scope The scope that the link should be unwrapped in
* @return The linked element
*
* @throws FluentPatternException If the linked element does not exist this Exception should be thrown
*/
FluentPattern unwrap(final FluentScope scope) throws FluentPatternException;

/**
* Returns a simple string variant of the data that this element contains
*
* @param scope The scope in which this operation should be done
* @return A simple string
*/
String toSimpleString(final FluentScope scope);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package net.quickwrite.fluent4j.ast;

import net.quickwrite.fluent4j.container.FluentScope;
import net.quickwrite.fluent4j.result.ResultBuilder;

/**
* The base element for the construction of the message.
*/
public interface FluentResolvable {
/**
* @param scope The scope which contains the necessary information for this element.
* @param builder The ResultBuilder used for resolving the entity.
*/
void resolve(final FluentScope scope, final ResultBuilder builder);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package net.quickwrite.fluent4j.ast.entry;

import net.quickwrite.fluent4j.ast.FluentResolvable;
import net.quickwrite.fluent4j.ast.identifier.FluentIdentifier;

import java.util.List;
import java.util.Optional;

public interface FluentAttributeEntry extends FluentEntry {
/**
* Returns a list of attributes that this entry has.
*
* <p>
* If there are no entries this should return
* an empty list.
* </p>
*
* @return A list of attributes
*/
FluentAttributeEntry.Attribute[] getAttributes();

/**
* Returns the specific attribute with the given
* identifier.
* <br />
* If the attribute doesn't exist it will return
* an empty optional.
*
* <p>
* This search for the attribute is a linear search
* with the default implementation and with that has
* a time complexity of {@code O(n)}.
* </p>
*
* @param identifier The identifier of the attribute
* @return The attribute
*/
default Optional<FluentAttributeEntry.Attribute> getAttribute(final String identifier) {
for (final FluentAttributeEntry.Attribute attribute : getAttributes()) {
if(attribute.getIdentifier().getSimpleIdentifier().equals(identifier)) {
return Optional.of(attribute);
}
}

return Optional.empty();
}

/**
* A single attribute of the FluentEntry.
*/
interface Attribute extends FluentResolvable {
/**
* Returns the identifier of the attribute
*
* @return The identifier
*/
FluentIdentifier<String> getIdentifier();

/**
* Returns a boolean if the attribute itself can
* be successfully used in a selectable.
*
* @return If the attribute is selectable
*/
boolean isSelectable();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.quickwrite.fluent4j.ast.entry;

import net.quickwrite.fluent4j.ast.FluentPattern;
import net.quickwrite.fluent4j.ast.FluentResolvable;
import net.quickwrite.fluent4j.ast.identifier.FluentIdentifier;

/**
* Represents a single entry that is being used
* inside the parsed resource that holds the translation
* content based upon an identifier.
*/
public interface FluentEntry extends FluentResolvable, FluentPattern {
/**
* Returns the identifier of this specific entry
*
* @return The identifier
*/
FluentIdentifier<String> getIdentifier();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.quickwrite.fluent4j.ast.entry;

/**
* Represents a FluentMessage specifically
*/
public interface FluentMessage extends FluentAttributeEntry {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package net.quickwrite.fluent4j.ast.identifier;

/**
* The FluentIdentifier interface represents an identifier.
* Identifiers are used to represent names or keys within the localization messages.
*
* @param <I> The type of the identifier
*/
public interface FluentIdentifier<I> {
/**
* Retrieves the simple form of the identifier.
* The simple form typically represents the short name or key.
*
* @return The simple form of the identifier
*/
I getSimpleIdentifier();

/**
* Retrieves the full form of the identifier.
* The full form may represent the complete identifier with any additional context or namespace.
*
* @return The full form of the identifier
*/
I getFullIdentifier();

/**
* Calculates the hash code of the identifier.
*
* @return The hash code of the identifier
*/
int hashCode();

/**
* Compares this identifier to the specified object for equality.
* Two identifiers are considered equal if their simple forms are equal.
*
* @param o The object to compare with
* @return true if the specified object is equal to this identifier, false otherwise
*/
boolean equals(final Object o);
}
Loading

0 comments on commit 5829fb2

Please sign in to comment.