add interpolation library of Luis Antunes
This commit is contained in:
parent
336cebca9d
commit
7d025d5002
21 changed files with 1398 additions and 3 deletions
202
datastructures-interpolation/LICENSE.txt
Normal file
202
datastructures-interpolation/LICENSE.txt
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
9
datastructures-interpolation/NOTICE.txt
Normal file
9
datastructures-interpolation/NOTICE.txt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
This work is taken from
|
||||||
|
|
||||||
|
https://github.com/lantunes/interpolatd
|
||||||
|
|
||||||
|
as of Sep 29, 2023
|
||||||
|
|
||||||
|
by Luis Antunes
|
||||||
|
|
||||||
|
Apache License 2.0
|
|
@ -0,0 +1,3 @@
|
||||||
|
module org.xbib.datastructures.interpolation {
|
||||||
|
exports org.xbib.datastructures.interpolation;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
public interface EnclosureClosingHandler<T> extends SubstitutionHandler<T> {
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class EnclosureClosingHandlerImpl<T> extends SubstitutionHandlerImpl<T>
|
||||||
|
implements EnclosureClosingHandler<T> {
|
||||||
|
|
||||||
|
private final String opening;
|
||||||
|
private final String closing;
|
||||||
|
|
||||||
|
private final Pattern pattern;
|
||||||
|
|
||||||
|
public EnclosureClosingHandlerImpl(String opening, String closing, String characterClass) {
|
||||||
|
this.opening = opening;
|
||||||
|
this.closing = closing;
|
||||||
|
String quotedOpening = Pattern.quote(opening);
|
||||||
|
String quotedClosing = Pattern.quote(closing);
|
||||||
|
if (characterClass == null) {
|
||||||
|
characterClass = "[^" + quotedOpening + quotedClosing + "\\s]+";
|
||||||
|
}
|
||||||
|
this.pattern = Pattern.compile("(" + quotedOpening + characterClass + quotedClosing + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Pattern getPattern() {
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCaptured(String found) {
|
||||||
|
return found.substring(opening.length(), found.length() - closing.length());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
public interface EnclosureOpeningHandler<T> {
|
||||||
|
|
||||||
|
EnclosureClosingHandler<T> and(String closing);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
public class EnclosureOpeningHandlerImpl<T> implements EnclosureOpeningHandler<T> {
|
||||||
|
|
||||||
|
private final String opening;
|
||||||
|
|
||||||
|
private final String characterClass;
|
||||||
|
|
||||||
|
private EnclosureClosingHandlerImpl<T> closingHandler;
|
||||||
|
|
||||||
|
public EnclosureOpeningHandlerImpl(String opening, String characterClass) {
|
||||||
|
this.opening = opening;
|
||||||
|
this.characterClass = characterClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnclosureClosingHandler<T> and(String closing) {
|
||||||
|
EnclosureClosingHandlerImpl<T> closingHandler =
|
||||||
|
new EnclosureClosingHandlerImpl<T>(opening, closing, characterClass);
|
||||||
|
this.closingHandler = closingHandler;
|
||||||
|
return closingHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnclosureClosingHandlerImpl<T> getEnclosureClosingHandler() {
|
||||||
|
return closingHandler;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class EscapeHandler<T> implements Interpolating<T> {
|
||||||
|
|
||||||
|
private final String escape;
|
||||||
|
private final Pattern pattern;
|
||||||
|
|
||||||
|
public EscapeHandler(String escape) {
|
||||||
|
this.escape = escape;
|
||||||
|
this.pattern = Pattern.compile("(" + Pattern.quote(escape) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Substitution> interpolate(String toInterpolate, T arg) {
|
||||||
|
List<Substitution> substitutions = new ArrayList<Substitution>();
|
||||||
|
Matcher m = pattern.matcher(toInterpolate);
|
||||||
|
while (m.find()) {
|
||||||
|
substitutions.add(new Substitution(escape, "", m.start(), m.end(), true));
|
||||||
|
}
|
||||||
|
return substitutions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface Interpolating<T> {
|
||||||
|
|
||||||
|
List<Substitution> interpolate(String toInterpolate, T arg);
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
public interface InterpolationHandler<T> {
|
||||||
|
|
||||||
|
PrefixHandler<T> prefixedBy(String prefix);
|
||||||
|
|
||||||
|
EnclosureOpeningHandler<T> enclosedBy(String opening);
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class InterpolationHandlerImpl<T> implements InterpolationHandler<T>, Interpolating<T> {
|
||||||
|
|
||||||
|
private final String characterClass;
|
||||||
|
|
||||||
|
private PrefixHandlerImpl<T> prefixHandler;
|
||||||
|
|
||||||
|
private EnclosureOpeningHandlerImpl<T> enclosureOpeningHandler;
|
||||||
|
|
||||||
|
public InterpolationHandlerImpl() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InterpolationHandlerImpl(String characterClass) {
|
||||||
|
this.characterClass = characterClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrefixHandler<T> prefixedBy(String prefix) {
|
||||||
|
PrefixHandlerImpl<T> prefixHandler = new PrefixHandlerImpl<T>(prefix, characterClass);
|
||||||
|
this.prefixHandler = prefixHandler;
|
||||||
|
return prefixHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnclosureOpeningHandler<T> enclosedBy(String opening) {
|
||||||
|
EnclosureOpeningHandlerImpl<T> enclosureOpeningHandler =
|
||||||
|
new EnclosureOpeningHandlerImpl<T>(opening, characterClass);
|
||||||
|
this.enclosureOpeningHandler = enclosureOpeningHandler;
|
||||||
|
return enclosureOpeningHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Substitution> interpolate(String toInterpolate, T arg) {
|
||||||
|
List<Substitution> substitutions = new ArrayList<Substitution>();
|
||||||
|
if (prefixHandler != null) {
|
||||||
|
substitutions.addAll(prefixHandler.interpolate(toInterpolate, arg));
|
||||||
|
|
||||||
|
} else if (enclosureOpeningHandler != null) {
|
||||||
|
substitutions.addAll(enclosureOpeningHandler.getEnclosureClosingHandler()
|
||||||
|
.interpolate(toInterpolate, arg));
|
||||||
|
}
|
||||||
|
return substitutions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Interpolator<T> {
|
||||||
|
|
||||||
|
private final List<Interpolating<T>> interpolating = new ArrayList<>();
|
||||||
|
|
||||||
|
public Interpolator() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public InterpolationHandler<T> when() {
|
||||||
|
InterpolationHandlerImpl<T> handler = new InterpolationHandlerImpl<T>();
|
||||||
|
interpolating.add(handler);
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InterpolationHandler<T> when(String characterClass) {
|
||||||
|
InterpolationHandlerImpl<T> handler = new InterpolationHandlerImpl<T>(characterClass);
|
||||||
|
interpolating.add(handler);
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void escapeWith(String escape) {
|
||||||
|
interpolating.add(new EscapeHandler<T>(escape));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String interpolate(String toInterpolate, T arg) {
|
||||||
|
List<Substitution> substitutions = new ArrayList<Substitution>();
|
||||||
|
for (Interpolating<T> handler : interpolating) {
|
||||||
|
substitutions.addAll(handler.interpolate(toInterpolate, arg));
|
||||||
|
}
|
||||||
|
Collections.sort(substitutions);
|
||||||
|
StringBuilder sb = new StringBuilder(toInterpolate);
|
||||||
|
int diff = 0;
|
||||||
|
int lastEnd = 0;
|
||||||
|
Substitution lastEscape = null;
|
||||||
|
for (int i = 0; i < substitutions.size(); i++) {
|
||||||
|
Substitution sub = substitutions.get(i);
|
||||||
|
if (sub.start() < lastEnd) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sub.isEscape()) {
|
||||||
|
if (lastEscape != null && sub.isAfter(lastEscape)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isActualEscape(sub, substitutions, i)) {
|
||||||
|
lastEscape = sub;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (lastEscape != null && sub.isAfter(lastEscape)) {
|
||||||
|
lastEnd = sub.end();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (sub.value() == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sb.replace(sub.start() - diff, sub.end() - diff, sub.value());
|
||||||
|
diff += sub.found().length() - sub.value().length();
|
||||||
|
lastEnd = sub.end();
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isActualEscape(Substitution esc, List<Substitution> substitutions, int index) {
|
||||||
|
if (!hasNext(substitutions, index)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Substitution nextSub = getNext(substitutions, index);
|
||||||
|
if (!nextSub.isAfter(esc)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!nextSub.isEscape()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return isActualEscape(nextSub, substitutions, ++index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasNext(List<Substitution> substitutions, int currentIndex) {
|
||||||
|
return (currentIndex + 1) < substitutions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Substitution getNext(List<Substitution> substitutions, int currentIndex) {
|
||||||
|
return substitutions.get(currentIndex + 1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
public interface PrefixHandler<T> extends SubstitutionHandler<T> {
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class PrefixHandlerImpl<T> extends SubstitutionHandlerImpl<T> implements PrefixHandler<T> {
|
||||||
|
|
||||||
|
private final Pattern pattern;
|
||||||
|
|
||||||
|
private final String prefix;
|
||||||
|
|
||||||
|
public PrefixHandlerImpl(String prefix, String characterClass) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
String quotedPrefix = Pattern.quote(prefix);
|
||||||
|
if (characterClass == null) {
|
||||||
|
characterClass = "[^" + quotedPrefix + "\\s]+";
|
||||||
|
}
|
||||||
|
this.pattern = Pattern.compile("(" + quotedPrefix + characterClass + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Pattern getPattern() {
|
||||||
|
return pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getCaptured(String found) {
|
||||||
|
return found.substring(prefix.length());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
public class Substitution implements Comparable<Substitution> {
|
||||||
|
|
||||||
|
private final String found;
|
||||||
|
private final String value;
|
||||||
|
private final int start;
|
||||||
|
private final int end;
|
||||||
|
private final boolean escape;
|
||||||
|
|
||||||
|
public Substitution(String found, String value, int start, int end) {
|
||||||
|
this(found, value, start, end, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Substitution(String found, String value, int start, int end, boolean escape) {
|
||||||
|
this.found = found;
|
||||||
|
this.value = value;
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
this.escape = escape;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String found() {
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String value() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int start() {
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int end() {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEscape() {
|
||||||
|
return escape;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAfter(Substitution that) {
|
||||||
|
return this.start() == that.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Substitution that) {
|
||||||
|
return Integer.compare(this.start, that.start);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
public interface SubstitutionHandler<T> {
|
||||||
|
|
||||||
|
void handleWith(Substitutor<T> substitutor);
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public abstract class SubstitutionHandlerImpl<T> implements SubstitutionHandler<T>, Interpolating<T> {
|
||||||
|
|
||||||
|
protected Substitutor<T> substitutor;
|
||||||
|
|
||||||
|
public SubstitutionHandlerImpl() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleWith(Substitutor<T> substitutor) {
|
||||||
|
this.substitutor = substitutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Pattern getPattern();
|
||||||
|
|
||||||
|
protected abstract String getCaptured(String found);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Substitution> interpolate(String toInterpolate, T arg) {
|
||||||
|
List<Substitution> substitutions = new ArrayList<Substitution>();
|
||||||
|
if (substitutor != null) {
|
||||||
|
Matcher m = getPattern().matcher(toInterpolate);
|
||||||
|
while (m.find()) {
|
||||||
|
String found = m.group(1);
|
||||||
|
String captured = getCaptured(found);
|
||||||
|
String substitution = substitutor.substitute(captured, arg);
|
||||||
|
substitutions.add(new Substitution(found, substitution, m.start(), m.end()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return substitutions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package org.xbib.datastructures.interpolation;
|
||||||
|
|
||||||
|
public interface Substitutor<T> {
|
||||||
|
|
||||||
|
String substitute(String captured, T arg);
|
||||||
|
}
|
|
@ -0,0 +1,796 @@
|
||||||
|
package org.xbib.datastructures.interpolation.test;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.xbib.datastructures.interpolation.Interpolator;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
public class TestInterpolator {
|
||||||
|
|
||||||
|
private Interpolator<ValueMap> interpolator;
|
||||||
|
|
||||||
|
private ValueMap map;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void beforeEachTest() {
|
||||||
|
interpolator = new Interpolator<>();
|
||||||
|
interpolator.when("[a-zA-Z0-9_]+").prefixedBy(":")
|
||||||
|
.handleWith((captured, map) -> map.getForPrefixed(captured));
|
||||||
|
interpolator.when("[0-9]+").enclosedBy("*[").and("]")
|
||||||
|
.handleWith((captured, map) -> map.getForPrefixedBracketEnclosed(captured));
|
||||||
|
interpolator.when().enclosedBy("{").and("}")
|
||||||
|
.handleWith((captured, map) -> map.getForBraceEnclosed(captured));
|
||||||
|
interpolator.when().enclosedBy("[").and("]")
|
||||||
|
.handleWith((captured, map) -> map.getForBracketEnclosed(captured));
|
||||||
|
interpolator.escapeWith("^");
|
||||||
|
map = new ValueMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStringReturnedUnmodifiedWhenNoSubstitutionsArePresent() {
|
||||||
|
map.put("foo", new Value().forPrefixed("bar"));
|
||||||
|
assertEquals("Hello World!",
|
||||||
|
interpolator.interpolate("Hello World!", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSubstitued() {
|
||||||
|
map.put("name", new Value().forPrefixed("Tim"));
|
||||||
|
assertEquals("Hello Tim",
|
||||||
|
interpolator.interpolate("Hello :name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSubstituedInPresenceOfOtherStandalonePrefixes() {
|
||||||
|
map.put("name", new Value().forPrefixed("Tim"));
|
||||||
|
assertEquals("Hello : Tim :",
|
||||||
|
interpolator.interpolate("Hello : :name :", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedDoublyPrefixedIsSubstitued() {
|
||||||
|
map.put("name", new Value().forPrefixed("Tim"));
|
||||||
|
assertEquals("Hello :Tim",
|
||||||
|
interpolator.interpolate("Hello ::name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedEnclosedByPrefixesIsSubstitued() {
|
||||||
|
map.put("name", new Value().forPrefixed("Tim"));
|
||||||
|
assertEquals("Hello :Tim:",
|
||||||
|
interpolator.interpolate("Hello ::name:", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSubstituedInPresenceOfOtherPrefixedTerms() {
|
||||||
|
map.put("name", new Value().forPrefixed("Tim"));
|
||||||
|
assertEquals("Hello :someTerm Tim",
|
||||||
|
interpolator.interpolate("Hello :someTerm :name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSubstituedWithPrefixContainingValue() {
|
||||||
|
map.put("name", new Value().forPrefixed(":Tim"));
|
||||||
|
assertEquals("Hello :Tim",
|
||||||
|
interpolator.interpolate("Hello :name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimilarPrefixedSubstitued() {
|
||||||
|
map.put("name", new Value().forPrefixed("Tim"));
|
||||||
|
map.put("name1", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello Tim John",
|
||||||
|
interpolator.interpolate("Hello :name :name1", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSimilarPrefixedNotSubstitued() {
|
||||||
|
map.put("name", new Value().forPrefixed("Tim"));
|
||||||
|
assertEquals("Hello :name1",
|
||||||
|
interpolator.interpolate("Hello :name1", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrefixedSubstitutedWithNameOfAnotherPrefix() {
|
||||||
|
map.put("name", new Value().forPrefixed(":id"));
|
||||||
|
map.put("id", new Value().forPrefixed("1"));
|
||||||
|
assertEquals("Hello :id 1",
|
||||||
|
interpolator.interpolate("Hello :name :id", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiplePrefixedSubstitued() {
|
||||||
|
map.put("firstName", new Value().forPrefixed("John"));
|
||||||
|
map.put("lastName", new Value().forPrefixed("Doe"));
|
||||||
|
assertEquals("Hello John Doe",
|
||||||
|
interpolator.interpolate("Hello :firstName :lastName", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiplePrefixedSubstituedInPresenceOfOtherPrefixed() {
|
||||||
|
map.put("firstName", new Value().forPrefixed("John"));
|
||||||
|
map.put("lastName", new Value().forPrefixed("Doe"));
|
||||||
|
assertEquals("Hello : John : Doe :",
|
||||||
|
interpolator.interpolate("Hello : :firstName : :lastName :", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiplePrefixedSubstituedWithPrefixContainingValues() {
|
||||||
|
map.put("firstName", new Value().forPrefixed(":John"));
|
||||||
|
map.put("lastName", new Value().forPrefixed(":Doe"));
|
||||||
|
assertEquals("Hello :John :Doe",
|
||||||
|
interpolator.interpolate("Hello :firstName :lastName", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleBraceEnclosedSubstitued() {
|
||||||
|
map.put("name", new Value().forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello Tim",
|
||||||
|
interpolator.interpolate("Hello {name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBraceEnclosedWithPrefixedNameNotSubstituted() {
|
||||||
|
map.put("name", new Value().forPrefixed("John")
|
||||||
|
.forBraceEnclosed(":name"));
|
||||||
|
assertEquals("Hello :name",
|
||||||
|
interpolator.interpolate("Hello {name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrefixedWithBraceEnclosedNameNotSubstituted() {
|
||||||
|
map.put("name", new Value().forPrefixed("{name}")
|
||||||
|
.forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello {name}",
|
||||||
|
interpolator.interpolate("Hello :name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleBraceEnclosedSubstituedInPresenceOfOtherBraces() {
|
||||||
|
map.put("name", new Value().forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello { Tim } {",
|
||||||
|
interpolator.interpolate("Hello { {name} } {", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleBraceEnclosedSubstituedInPresenceOfOtherBraces_NoSpaces() {
|
||||||
|
map.put("name", new Value().forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello {Tim} {",
|
||||||
|
interpolator.interpolate("Hello {{name}} {", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleBraceEnclosedSubstituedInPresenceOfOtherBraceEnclosedTerms() {
|
||||||
|
map.put("name", new Value().forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello {there} Tim",
|
||||||
|
interpolator.interpolate("Hello {there} {name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleBraceEnclosedSubstituedWithBraceEnclosedValue() {
|
||||||
|
map.put("name", new Value().forBraceEnclosed("{Tim}"));
|
||||||
|
assertEquals("Hello {Tim}",
|
||||||
|
interpolator.interpolate("Hello {name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleBraceEnclosedSubstitued() {
|
||||||
|
map.put("firstName", new Value().forBraceEnclosed("John"));
|
||||||
|
map.put("lastName", new Value().forBraceEnclosed("Doe"));
|
||||||
|
assertEquals("Hello John Doe",
|
||||||
|
interpolator.interpolate("Hello {firstName} {lastName}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleBraceEnclosedSubstituedInPresenceOfOtherBraces() {
|
||||||
|
map.put("firstName", new Value().forBraceEnclosed("John"));
|
||||||
|
map.put("lastName", new Value().forBraceEnclosed("Doe"));
|
||||||
|
assertEquals("Hello { John } { Doe } {",
|
||||||
|
interpolator.interpolate("Hello { {firstName} } { {lastName} } {", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleBraceEnclosedSubstituedInPresenceOfOtherBraces_NoSpaces() {
|
||||||
|
map.put("firstName", new Value().forBraceEnclosed("John"));
|
||||||
|
map.put("lastName", new Value().forBraceEnclosed("Doe"));
|
||||||
|
assertEquals("Hello {John} {Doe} {",
|
||||||
|
interpolator.interpolate("Hello {{firstName}} {{lastName}} {", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleBraceEnclosedSubstituedInPresenceOfOtherBraceEnclosedTerms() {
|
||||||
|
map.put("firstName", new Value().forBraceEnclosed("John"));
|
||||||
|
map.put("lastName", new Value().forBraceEnclosed("Doe"));
|
||||||
|
assertEquals("Hello {there} John Doe",
|
||||||
|
interpolator.interpolate("Hello {there} {firstName} {lastName}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleBraceEnclosedSubstituedWithBraceEnclosedValue() {
|
||||||
|
map.put("firstName", new Value().forBraceEnclosed("{John}"));
|
||||||
|
map.put("lastName", new Value().forBraceEnclosed("{Doe}"));
|
||||||
|
assertEquals("Hello {John} {Doe}",
|
||||||
|
interpolator.interpolate("Hello {firstName} {lastName}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrefixedAndBraceEnclosed_PrefixedValuesComeFirst() {
|
||||||
|
map.put("salutation", new Value().forPrefixed("Mr."));
|
||||||
|
map.put("firstName", new Value().forBraceEnclosed("John"));
|
||||||
|
map.put("lastName", new Value().forBraceEnclosed("Doe"));
|
||||||
|
assertEquals("Hello Mr. John Doe",
|
||||||
|
interpolator.interpolate("Hello :salutation {firstName} {lastName}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrefixedAndBraceEnclosed_BraceEnclosedComeFirst() {
|
||||||
|
map.put("salutation", new Value().forBraceEnclosed("Mr."));
|
||||||
|
map.put("firstName", new Value().forPrefixed("John"));
|
||||||
|
map.put("lastName", new Value().forPrefixed("Doe"));
|
||||||
|
assertEquals("Hello Mr. John Doe",
|
||||||
|
interpolator.interpolate("Hello {salutation} :firstName :lastName", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testColonPrefixedBraceEnclosed() {
|
||||||
|
map.put("{name}", new Value().forPrefixed("John"));
|
||||||
|
map.put("name", new Value().forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello :Tim",
|
||||||
|
interpolator.interpolate("Hello :{name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBraceEnclosedPrefixedValueSubstitutesBraceEnclosed_OneOccurrence() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
map.put(":name", new Value().forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello Tim",
|
||||||
|
interpolator.interpolate("Hello {:name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBraceEnclosedPrefixedValueSubstitutesBraceEnclosed_TwoOccurrences() {
|
||||||
|
map.put("first", new Value().forPrefixed("John"));
|
||||||
|
map.put("last", new Value().forPrefixed("Doe"));
|
||||||
|
map.put(":first", new Value().forBraceEnclosed("Tom"));
|
||||||
|
map.put(":last", new Value().forBraceEnclosed("Jerry"));
|
||||||
|
assertEquals("Hello Tom Jerry",
|
||||||
|
interpolator.interpolate("Hello {:first} {:last}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSquareBracketUnknownValuesIgnored() throws Exception {
|
||||||
|
map.put("request.body", new Value().forBracketEnclosed("Hello World!"));
|
||||||
|
assertEquals("Message: [some.value]",
|
||||||
|
interpolator.interpolate("Message: [some.value]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSquareBracketSubstituted() throws Exception {
|
||||||
|
map.put("request.body", new Value().forBracketEnclosed("Hello World!"));
|
||||||
|
assertEquals("Message: Hello World!",
|
||||||
|
interpolator.interpolate("Message: [request.body]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSquareBracketSubstituedInPresenceOfOtherSquareBrackets() throws Exception {
|
||||||
|
map.put("request.body", new Value().forBracketEnclosed("Hello World!"));
|
||||||
|
assertEquals("Message: [ Hello World! ] [",
|
||||||
|
interpolator.interpolate("Message: [ [request.body] ] [", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSquareBracketSubstituedInPresenceOfOtherSquareBrackets_NoSpaces() throws Exception {
|
||||||
|
map.put("request.body", new Value().forBracketEnclosed("Hello World!"));
|
||||||
|
assertEquals("Message: [Hello World!] [",
|
||||||
|
interpolator.interpolate("Message: [[request.body]] [", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSquareBracketSubstituedInPresenceOfOtherSquareBracketEnclosedTerms() throws Exception {
|
||||||
|
map.put("request.body", new Value().forBracketEnclosed("Tim"));
|
||||||
|
assertEquals("Hello [there] Tim",
|
||||||
|
interpolator.interpolate("Hello [there] [request.body]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSquareBracketSubstituedWithSquareBracketEnclosedValue() throws Exception {
|
||||||
|
map.put("request.body", new Value().forBracketEnclosed("[Tim]"));
|
||||||
|
assertEquals("Hello [Tim]",
|
||||||
|
interpolator.interpolate("Hello [request.body]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrefixedAndBraceEnclosedAndSquareBracketUsedTogether() throws Exception {
|
||||||
|
map.put("salutation", new Value().forBraceEnclosed("Mr."));
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
map.put("request.body", new Value().forBracketEnclosed("Doe"));
|
||||||
|
assertEquals("Hello Mr. John Doe",
|
||||||
|
interpolator.interpolate("Hello {salutation} :name [request.body]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSquareBracketSubstitued() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("Tim"));
|
||||||
|
assertEquals("Hello Tim",
|
||||||
|
interpolator.interpolate("Hello *[0]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSquareBracketSubstituedMultipleTimes() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("Tim"));
|
||||||
|
assertEquals("Hello Tim Tim",
|
||||||
|
interpolator.interpolate("Hello *[0] *[0]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSquareBracketNotSubstituedWithIncorrectIndex() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("Tim"));
|
||||||
|
assertEquals("Hello *[1]",
|
||||||
|
interpolator.interpolate("Hello *[1]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSquareBracketNotSubstituedIfFormattedIncorrectly() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("Tim"));
|
||||||
|
assertEquals("Hello *[ 0]",
|
||||||
|
interpolator.interpolate("Hello *[ 0]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSquareBracketSubstituedWithSplatContainingValue() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("*[0]"));
|
||||||
|
assertEquals("Hello *[0]",
|
||||||
|
interpolator.interpolate("Hello *[0]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePrefixedSquareBracketSubstituedWithEmptyValue() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed(""));
|
||||||
|
assertEquals("Hello ",
|
||||||
|
interpolator.interpolate("Hello *[0]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrefixedSquareBracketSubstituedWithDoubleDigitIndex() {
|
||||||
|
map.put("10", new Value().forPrefixedBracketEnclosed("k"));
|
||||||
|
assertEquals("Hello k",
|
||||||
|
interpolator.interpolate("Hello *[10]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoPrefixedSquareBracketsSubstitued() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("John"));
|
||||||
|
map.put("1", new Value().forPrefixedBracketEnclosed("Doe"));
|
||||||
|
assertEquals("Hello John Doe",
|
||||||
|
interpolator.interpolate("Hello *[0] *[1]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnlySecondOfTwoPrefixedSquareBracketsSubstitued() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("John"));
|
||||||
|
map.put("1", new Value().forPrefixedBracketEnclosed("Doe"));
|
||||||
|
assertEquals("Hello Doe",
|
||||||
|
interpolator.interpolate("Hello *[1]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubstitutionIncreasesOverallLengthOfString() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("hello"));
|
||||||
|
map.put("1", new Value().forPrefixedBracketEnclosed("there"));
|
||||||
|
assertEquals("hello there",
|
||||||
|
interpolator.interpolate("*[0] *[1]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSubstitutionDecreasesOverallLengthOfString() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("a"));
|
||||||
|
map.put("1", new Value().forPrefixedBracketEnclosed("b"));
|
||||||
|
assertEquals("a b",
|
||||||
|
interpolator.interpolate("*[0] *[1]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithSinglePrefixedWhichExists() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello :name",
|
||||||
|
interpolator.interpolate("Hello ^:name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithSinglePrefixedWhichDoesNotExist() {
|
||||||
|
assertEquals("Hello :name",
|
||||||
|
interpolator.interpolate("Hello ^:name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithMultiplePrefixed_OneEscaped() {
|
||||||
|
map.put("name1", new Value().forPrefixed("John"));
|
||||||
|
map.put("name2", new Value().forPrefixed("Doe"));
|
||||||
|
assertEquals("Hello :name1 Doe",
|
||||||
|
interpolator.interpolate("Hello ^:name1 :name2", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithMultiplePrefixed_MultipleEscaped() {
|
||||||
|
map.put("name1", new Value().forPrefixed("John"));
|
||||||
|
map.put("name2", new Value().forPrefixed("Doe"));
|
||||||
|
assertEquals("Hello :name1 :name2",
|
||||||
|
interpolator.interpolate("Hello ^:name1 ^:name2", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithMultiplePrefixed_MultipleEscapedConcatenated() {
|
||||||
|
map.put("name1", new Value().forPrefixed("John"));
|
||||||
|
map.put("name2", new Value().forPrefixed("Doe"));
|
||||||
|
assertEquals("Hello :name1:name2",
|
||||||
|
interpolator.interpolate("Hello ^:name1^:name2", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleEscapeWithPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello ^John",
|
||||||
|
interpolator.interpolate("Hello ^^:name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTripleEscapeWithPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello ^:name",
|
||||||
|
interpolator.interpolate("Hello ^^^:name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadrupleEscapeWithPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello ^^John",
|
||||||
|
interpolator.interpolate("Hello ^^^^:name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeOnItsOwn() {
|
||||||
|
assertEquals("Hello ^ there",
|
||||||
|
interpolator.interpolate("Hello ^ there", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleEscapeOnItsOwn() {
|
||||||
|
assertEquals("Hello ^^ there",
|
||||||
|
interpolator.interpolate("Hello ^^ there", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTripleEscapeOnItsOwn() {
|
||||||
|
assertEquals("Hello ^^^ there",
|
||||||
|
interpolator.interpolate("Hello ^^^ there", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadrupleEscapeOnItsOwn() {
|
||||||
|
assertEquals("Hello ^^^^ there",
|
||||||
|
interpolator.interpolate("Hello ^^^^ there", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeOnItsOwnWithPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello ^ John",
|
||||||
|
interpolator.interpolate("Hello ^ :name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleEscapeOnItsOwnWithPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello ^^ John",
|
||||||
|
interpolator.interpolate("Hello ^^ :name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTripleEscapeOnItsOwnWithPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello ^^^ John",
|
||||||
|
interpolator.interpolate("Hello ^^^ :name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadrupleEscapeOnItsOwnWithPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello ^^^^ John",
|
||||||
|
interpolator.interpolate("Hello ^^^^ :name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeNextToNonInterpolatedValue() {
|
||||||
|
assertEquals("Hello ^there",
|
||||||
|
interpolator.interpolate("Hello ^there", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleEscapeNextToNonInterpolatedValue() {
|
||||||
|
assertEquals("Hello ^^there",
|
||||||
|
interpolator.interpolate("Hello ^^there", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTripleEscapeNextToNonInterpolatedValue() {
|
||||||
|
assertEquals("Hello ^^^there",
|
||||||
|
interpolator.interpolate("Hello ^^^there", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadrupleEscapeNextToNonInterpolatedValue() {
|
||||||
|
assertEquals("Hello ^^^^there",
|
||||||
|
interpolator.interpolate("Hello ^^^^there", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeAfterPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello John^",
|
||||||
|
interpolator.interpolate("Hello :name^", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleEscapeAfterPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello John^^",
|
||||||
|
interpolator.interpolate("Hello :name^^", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTripleEscapeAfterPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello John^^^",
|
||||||
|
interpolator.interpolate("Hello :name^^^", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadrupleEscapeAfterPrefixed() {
|
||||||
|
map.put("name", new Value().forPrefixed("John"));
|
||||||
|
assertEquals("Hello John^^^^",
|
||||||
|
interpolator.interpolate("Hello :name^^^^", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeAfterNonInterpolatedValue() {
|
||||||
|
assertEquals("Hello there^",
|
||||||
|
interpolator.interpolate("Hello there^", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoubleEscapeAfterNonInterpolatedValue() {
|
||||||
|
assertEquals("Hello there^^",
|
||||||
|
interpolator.interpolate("Hello there^^", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTripleEscapeAfterNonInterpolatedValue() {
|
||||||
|
assertEquals("Hello there^^^",
|
||||||
|
interpolator.interpolate("Hello there^^^", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testQuadrupleEscapeAfterNonInterpolatedValue() {
|
||||||
|
assertEquals("Hello there^^^^",
|
||||||
|
interpolator.interpolate("Hello there^^^^", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeIgnoredInsideBraceEnclosed() {
|
||||||
|
map.put("^name", new Value().forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello Tim",
|
||||||
|
interpolator.interpolate("Hello {^name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithSingleBraceEnclosedWhichExists() {
|
||||||
|
map.put("name", new Value().forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello {name}",
|
||||||
|
interpolator.interpolate("Hello ^{name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithSingleBraceEnclosedWhichDoesNotExist() {
|
||||||
|
assertEquals("Hello {name}",
|
||||||
|
interpolator.interpolate("Hello ^{name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithMultipleBraceEnclosed_OneEscaped() {
|
||||||
|
map.put("firstName", new Value().forBraceEnclosed("John"));
|
||||||
|
map.put("lastName", new Value().forBraceEnclosed("Doe"));
|
||||||
|
assertEquals("Hello {firstName} Doe",
|
||||||
|
interpolator.interpolate("Hello ^{firstName} {lastName}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithMultipleBraceEnclosed_MultipleEscaped() {
|
||||||
|
map.put("firstName", new Value().forBraceEnclosed("John"));
|
||||||
|
map.put("lastName", new Value().forBraceEnclosed("Doe"));
|
||||||
|
assertEquals("Hello {firstName} {lastName}",
|
||||||
|
interpolator.interpolate("Hello ^{firstName} ^{lastName}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithSingleSquareBracketWhichExists() throws Exception {
|
||||||
|
map.put("request?name", new Value().forBracketEnclosed("Tim"));
|
||||||
|
assertEquals("Hello [request?name]",
|
||||||
|
interpolator.interpolate("Hello ^[request?name]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithSingleSquareBracketWhichDoesNotExist() throws Exception {
|
||||||
|
assertEquals("Hello [request?name]",
|
||||||
|
interpolator.interpolate("Hello ^[request?name]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithMultipleSquareBrackets_OneEscaped() throws Exception {
|
||||||
|
map.put("request?name1", new Value().forBracketEnclosed("John"));
|
||||||
|
map.put("request?name2", new Value().forBracketEnclosed("Doe"));
|
||||||
|
assertEquals("Hello [request?name1] Doe",
|
||||||
|
interpolator.interpolate("Hello ^[request?name1] [request?name2]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithMultipleSquareBrackets_MultipleEscaped() throws Exception {
|
||||||
|
map.put("request?name1", new Value().forBracketEnclosed("John"));
|
||||||
|
map.put("request?name2", new Value().forBracketEnclosed("Doe"));
|
||||||
|
assertEquals("Hello [request?name1] [request?name2]",
|
||||||
|
interpolator.interpolate("Hello ^[request?name1] ^[request?name2]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithSinglePrefixedSquareBracketWhichExists() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("Tim"));
|
||||||
|
assertEquals("Hello *[0]",
|
||||||
|
interpolator.interpolate("Hello ^*[0]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithSinglePrefixedSquareBracketWhichDoesNotExist() {
|
||||||
|
assertEquals("Hello *[0]",
|
||||||
|
interpolator.interpolate("Hello ^*[0]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithMultiplePrefixedSquareBrackets_OneEscaped() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("John"));
|
||||||
|
map.put("1", new Value().forPrefixedBracketEnclosed("Doe"));
|
||||||
|
assertEquals("Hello *[0] Doe",
|
||||||
|
interpolator.interpolate("Hello ^*[0] *[1]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithMultiplePrefixedSquareBrackets_MultipleEscaped() {
|
||||||
|
map.put("0", new Value().forPrefixedBracketEnclosed("John"));
|
||||||
|
map.put("1", new Value().forPrefixedBracketEnclosed("Doe"));
|
||||||
|
assertEquals("Hello *[0] *[1]",
|
||||||
|
interpolator.interpolate("Hello ^*[0] ^*[1]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeBraceEnclosedWithPrefixedName() {
|
||||||
|
map.put("name", new Value().forPrefixed("John")
|
||||||
|
.forBraceEnclosed(":name"));
|
||||||
|
assertEquals("Hello {name}",
|
||||||
|
interpolator.interpolate("Hello ^{name}", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapePrefixedWithBraceEnclosedName() {
|
||||||
|
map.put("name", new Value().forPrefixed("{name}")
|
||||||
|
.forBraceEnclosed("Tim"));
|
||||||
|
assertEquals("Hello :name",
|
||||||
|
interpolator.interpolate("Hello ^:name", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPrefixedBracketEnclosedSubstitutedForAny() {
|
||||||
|
map.put("0", new Value().forAny("John"));
|
||||||
|
assertEquals("Hello John",
|
||||||
|
interpolator.interpolate("Hello *[0]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testEscapeWithSinglePrefixedSquareBracketWhichExistsForAny() {
|
||||||
|
map.put("0", new Value().forAny("Tim"));
|
||||||
|
assertEquals("Hello *[0]",
|
||||||
|
interpolator.interpolate("Hello ^*[0]", map));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ValueMap {
|
||||||
|
|
||||||
|
private final Map<String, Value> map = new HashMap<>();
|
||||||
|
|
||||||
|
public void put(String key, Value value) {
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForPrefixed(String captured) {
|
||||||
|
Value val = map.get(captured);
|
||||||
|
if (hasForAny(val)) return val.getForAny();
|
||||||
|
return val != null ? val.getForPrefixed() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForBraceEnclosed(String captured) {
|
||||||
|
Value val = map.get(captured);
|
||||||
|
if (hasForAny(val)) return val.getForAny();
|
||||||
|
return val != null ? val.getForBraceEnclosed() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForBracketEnclosed(String captured) {
|
||||||
|
Value val = map.get(captured);
|
||||||
|
if (hasForAny(val)) return val.getForAny();
|
||||||
|
return val != null ? val.getForBracketEnclosed() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForPrefixedBracketEnclosed(String captured) {
|
||||||
|
Value val = map.get(captured);
|
||||||
|
if (hasForAny(val)) return val.getForAny();
|
||||||
|
return val != null ? val.getForPrefixedBracketEnclosed() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasForAny(Value val) {
|
||||||
|
return val != null && val.getForAny() != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Value {
|
||||||
|
|
||||||
|
private String forAny;
|
||||||
|
private String forPrefixed;
|
||||||
|
private String forBraceEnclosed;
|
||||||
|
private String forBracketEnclosed;
|
||||||
|
private String forPrefixedBracketEnclosed;
|
||||||
|
|
||||||
|
public Value forAny(String val) {
|
||||||
|
forAny = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value forPrefixed(String val) {
|
||||||
|
forPrefixed = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value forBraceEnclosed(String val) {
|
||||||
|
forBraceEnclosed = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value forBracketEnclosed(String val) {
|
||||||
|
forBracketEnclosed = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Value forPrefixedBracketEnclosed(String val) {
|
||||||
|
forPrefixedBracketEnclosed = val;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForAny() {
|
||||||
|
return forAny;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForPrefixed() {
|
||||||
|
return forPrefixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForBraceEnclosed() {
|
||||||
|
return forBraceEnclosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForBracketEnclosed() {
|
||||||
|
return forBracketEnclosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getForPrefixedBracketEnclosed() {
|
||||||
|
return forPrefixedBracketEnclosed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
group = org.xbib
|
group = org.xbib
|
||||||
name = datastructures
|
name = datastructures
|
||||||
version = 2.3.1
|
version = 2.4.0
|
||||||
|
|
||||||
org.gradle.warning.mode = all
|
org.gradle.warning.mode = all
|
||||||
|
|
|
@ -16,8 +16,8 @@ dependencyResolutionManagement {
|
||||||
versionCatalogs {
|
versionCatalogs {
|
||||||
libs {
|
libs {
|
||||||
version('gradle', '8.1.1')
|
version('gradle', '8.1.1')
|
||||||
version('junit', '5.9.3')
|
version('junit', '5.10.0')
|
||||||
version('jackson', '2.14.3')
|
version('jackson', '2.15.2')
|
||||||
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
||||||
library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
||||||
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
||||||
|
@ -43,6 +43,7 @@ dependencyResolutionManagement {
|
||||||
}
|
}
|
||||||
|
|
||||||
include 'datastructures-api'
|
include 'datastructures-api'
|
||||||
|
include 'datastructures-interpolation'
|
||||||
include 'datastructures-io'
|
include 'datastructures-io'
|
||||||
include 'datastructures-charset'
|
include 'datastructures-charset'
|
||||||
include 'datastructures-common'
|
include 'datastructures-common'
|
||||||
|
|
Loading…
Reference in a new issue