Skip to content

Commit d6cd85d

Browse files
committed
Fix cyclic-reference problem
1 parent 678af98 commit d6cd85d

File tree

10 files changed

+146
-25
lines changed

10 files changed

+146
-25
lines changed

src/main/java/net/quickwrite/fluent4j/ast/placeable/AttributeReference.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ public FluentElement getArgumentResult(final AccessorBundle bundle) {
7070
return this;
7171
}
7272

73+
if (bundle.getAccessedStorage().alreadyAccessed(attribute)) {
74+
return this;
75+
}
76+
77+
bundle.getAccessedStorage().addElement(attribute);
78+
7379
final List<FluentElement> elementList = attribute.getElements();
7480

7581
if (elementList.size() != 1) {

src/main/java/net/quickwrite/fluent4j/ast/placeable/MessageReference.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ public String stringValue() {
3737

3838
@Override
3939
public CharSequence getResult(final AccessorBundle bundle) {
40-
return bundle
40+
return bundle
4141
.getBundle()
42-
.getMessage(this.stringValue(), bundle.getArguments())
42+
.getMessage(this.stringValue(), bundle)
4343
.orElse("{" + this.stringValue() + "}");
4444
}
4545

src/main/java/net/quickwrite/fluent4j/ast/placeable/TermReference.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ protected boolean check(final String string) {
4141

4242
@Override
4343
public CharSequence getResult(final AccessorBundle bundle) {
44-
return this.getArgumentResult(bundle).getResult(new AccessorElementsBundle(bundle.getBundle(), this.getArguments(bundle)));
44+
return bundle.getBundle()
45+
.getTerm(this.functionName, new AccessorElementsBundle(bundle.getBundle(), this.getArguments(bundle), bundle.getAccessedStorage()))
46+
.orElse("{-" + this.functionName + "}");
4547
}
4648

4749
/**
@@ -50,13 +52,7 @@ public CharSequence getResult(final AccessorBundle bundle) {
5052
*/
5153
@Override
5254
public FluentElement getArgumentResult(final AccessorBundle bundle) {
53-
final FluentTerm term = bundle.getBundle().getTerm(this.functionName);
54-
55-
if (term == null) {
56-
return new StringLiteral("{-" + this.functionName + "}");
57-
}
58-
59-
return term;
55+
return new StringLiteral(getResult(bundle).toString());
6056
}
6157

6258
@Override

src/main/java/net/quickwrite/fluent4j/ast/placeable/VariableReference.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public FluentElement getArgumentResult(final AccessorBundle bundle) {
6060
return new StringLiteral("{$" + content + "}");
6161
}
6262

63-
return arguments.getNamed(content);
63+
return argument;
6464
}
6565

6666
@Override

src/main/java/net/quickwrite/fluent4j/util/bundle/DirectFluentBundle.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import net.quickwrite.fluent4j.ast.FluentMessage;
44
import net.quickwrite.fluent4j.ast.FluentTerm;
5+
import net.quickwrite.fluent4j.util.bundle.args.AccessorBundle;
6+
7+
import java.util.Optional;
58

69
public interface DirectFluentBundle extends FluentBundle {
710
/**
@@ -21,6 +24,24 @@ public interface DirectFluentBundle extends FluentBundle {
2124
*/
2225
FluentTerm getTerm(final String key);
2326

27+
/**
28+
* Returns the {@link FluentTerm} that is being stored
29+
* for the {@code key}.
30+
*
31+
* <p>
32+
* So when the {@code .ftl}-files contain:
33+
* <pre>
34+
* -test = Hello World!
35+
* </pre>
36+
* it would return the {@link FluentTerm} for the key
37+
* {@code test} but {@code null} for anything else.
38+
*
39+
* @param bundle The bundle that is being used as an argument
40+
* @param key The key that the {@link FluentTerm} is stored in.
41+
* @return The term itself
42+
*/
43+
Optional<String> getTerm(final String key, final AccessorBundle bundle);
44+
2445
/**
2546
* Returns the {@link FluentMessage} that is being stored
2647
* for the {@code key}.
@@ -38,4 +59,23 @@ public interface DirectFluentBundle extends FluentBundle {
3859
* @return The message itself
3960
*/
4061
FluentMessage getMessage(final String key);
62+
63+
/**
64+
* Returns the {@link FluentMessage} that is being stored
65+
* for the {@code key}.
66+
*
67+
* <p>
68+
* So when the {@code .ftl}-files contain:
69+
* <pre>
70+
* test = Hello World!
71+
* </pre>
72+
* <p>
73+
* it would return the {@link FluentMessage} for the key
74+
* {@code test} but {@code null} for anything else.
75+
*
76+
* @param key The key that the {@link FluentMessage} is stored in.
77+
* @param bundle The bundle that is being used as an argument
78+
* @return The message itself
79+
*/
80+
Optional<String> getMessage(final String key, final AccessorBundle bundle);
4181
}

src/main/java/net/quickwrite/fluent4j/util/bundle/ResourceFluentBundle.java

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import net.quickwrite.fluent4j.functions.AbstractFunction;
1010
import net.quickwrite.fluent4j.util.BuiltinFunctions;
1111
import net.quickwrite.fluent4j.util.args.FluentArgs;
12+
import net.quickwrite.fluent4j.util.bundle.args.AccessedStorageBundle;
13+
import net.quickwrite.fluent4j.util.bundle.args.AccessorBundle;
1214
import net.quickwrite.fluent4j.util.bundle.args.AccessorElementsBundle;
1315

1416
import java.util.*;
@@ -48,16 +50,6 @@ public ResourceFluentBundle(final ULocale locale, final FluentResource resource)
4850
this.addResource(resource);
4951
}
5052

51-
@Override
52-
public FluentTerm getTerm(final String key) {
53-
return this.terms.get(key);
54-
}
55-
56-
@Override
57-
public FluentMessage getMessage(final String key) {
58-
return this.messages.get(key);
59-
}
60-
6153
@Override
6254
public void addResource(final FluentResource resource) {
6355
for (final FluentElement element : resource.getElements()) {
@@ -106,16 +98,60 @@ public boolean hasMessage(final String key) {
10698

10799
@Override
108100
public Optional<String> getMessage(final String key, final FluentArgs arguments) {
101+
return getMessage(
102+
key,
103+
new AccessorElementsBundle(
104+
this,
105+
arguments != null ? arguments : FluentArgs.EMPTY_ARGS,
106+
new AccessedStorageBundle())
107+
);
108+
}
109+
110+
@Override
111+
public FluentTerm getTerm(final String key) {
112+
return this.terms.get(key);
113+
}
114+
115+
@Override
116+
public Optional<String> getTerm(final String key, final AccessorBundle bundle) {
117+
final FluentTerm term = this.getTerm(key);
118+
119+
if (term == null) {
120+
return Optional.empty();
121+
}
122+
123+
if (bundle.getAccessedStorage().alreadyAccessed(term)) {
124+
return Optional.empty();
125+
}
126+
127+
bundle.getAccessedStorage().addElement(term);
128+
129+
return Optional.of(
130+
term.getResult(bundle).toString()
131+
);
132+
}
133+
134+
@Override
135+
public FluentMessage getMessage(final String key) {
136+
return this.messages.get(key);
137+
}
138+
139+
@Override
140+
public Optional<String> getMessage(final String key, final AccessorBundle bundle) {
109141
final FluentMessage message = this.getMessage(key);
110142

111143
if (message == null) {
112144
return Optional.empty();
113145
}
114146

147+
if (bundle.getAccessedStorage().alreadyAccessed(message)) {
148+
return Optional.empty();
149+
}
150+
151+
bundle.getAccessedStorage().addElement(message);
152+
115153
return Optional.of(
116-
message.getResult(
117-
new AccessorElementsBundle(this, arguments != null ? arguments : FluentArgs.EMPTY_ARGS)
118-
).toString()
154+
message.getResult(bundle).toString()
119155
);
120156
}
121157

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package net.quickwrite.fluent4j.util.bundle.args;
2+
3+
import net.quickwrite.fluent4j.ast.FluentBase;
4+
5+
public interface AccessedStorage {
6+
boolean alreadyAccessed(final FluentBase element);
7+
8+
void addElement(final FluentBase element);
9+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package net.quickwrite.fluent4j.util.bundle.args;
2+
3+
import net.quickwrite.fluent4j.ast.FluentBase;
4+
5+
import java.util.HashSet;
6+
import java.util.Set;
7+
8+
public class AccessedStorageBundle implements AccessedStorage {
9+
private final Set<FluentBase> elementSet;
10+
11+
public AccessedStorageBundle() {
12+
this.elementSet = new HashSet<>();
13+
}
14+
15+
@Override
16+
public boolean alreadyAccessed(final FluentBase element) {
17+
return this.elementSet.contains(element);
18+
}
19+
20+
@Override
21+
public void addElement(final FluentBase element) {
22+
this.elementSet.add(element);
23+
}
24+
}

src/main/java/net/quickwrite/fluent4j/util/bundle/args/AccessorBundle.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ public interface AccessorBundle {
77
DirectFluentBundle getBundle();
88

99
FluentArgs getArguments();
10+
11+
AccessedStorage getAccessedStorage();
1012
}

src/main/java/net/quickwrite/fluent4j/util/bundle/args/AccessorElementsBundle.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
public class AccessorElementsBundle implements AccessorBundle {
77
private final DirectFluentBundle bundle;
88
private final FluentArgs arguments;
9+
private final AccessedStorage accessedStorage;
910

10-
public AccessorElementsBundle(final DirectFluentBundle bundle, final FluentArgs arguments) {
11+
public AccessorElementsBundle(final DirectFluentBundle bundle, final FluentArgs arguments, final AccessedStorage accessedStorage) {
1112
this.bundle = bundle;
1213
this.arguments = arguments;
14+
15+
this.accessedStorage = accessedStorage;
1316
}
1417

1518
@Override
@@ -21,4 +24,9 @@ public DirectFluentBundle getBundle() {
2124
public FluentArgs getArguments() {
2225
return this.arguments;
2326
}
27+
28+
@Override
29+
public AccessedStorage getAccessedStorage() {
30+
return this.accessedStorage;
31+
}
2432
}

0 commit comments

Comments
 (0)