Skip to content

Commit 160ee9c

Browse files
authored
Merge pull request #190 from link-foundation/issue-189-7e97f19d7811
Add support for Java
2 parents a41c02d + 0d960ed commit 160ee9c

File tree

18 files changed

+3166
-2
lines changed

18 files changed

+3166
-2
lines changed

.github/workflows/java.yml

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
name: java
2+
3+
on:
4+
push:
5+
branches: main
6+
paths:
7+
- 'java/**'
8+
- '.github/workflows/java.yml'
9+
pull_request:
10+
paths:
11+
- 'java/**'
12+
- '.github/workflows/java.yml'
13+
14+
env:
15+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16+
17+
defaults:
18+
run:
19+
working-directory: java
20+
21+
jobs:
22+
findChangedJavaFiles:
23+
runs-on: ubuntu-latest
24+
timeout-minutes: 10
25+
outputs:
26+
isJavaFilesChanged: ${{ steps.setIsJavaFilesChangedOutput.outputs.isJavaFilesChanged }}
27+
steps:
28+
- uses: actions/checkout@v6
29+
with:
30+
fetch-depth: 0
31+
- name: Get changed files using defaults
32+
id: changed-files
33+
uses: tj-actions/changed-files@v47
34+
- name: Set output isJavaFilesChanged
35+
id: setIsJavaFilesChangedOutput
36+
run: |
37+
isJavaFilesChanged='false'
38+
echo "Changed files: ${{ steps.changed-files.outputs.all_changed_files }}"
39+
for changedFile in ${{ steps.changed-files.outputs.all_changed_files }}; do
40+
if [[ $changedFile == java/*.java ]] || [[ $changedFile == java/*.xml ]] || [[ $changedFile == java/* ]] || [[ $changedFile == .github/workflows/java.yml ]]; then
41+
echo "isJavaFilesChanged='true'"
42+
isJavaFilesChanged='true'
43+
break
44+
fi
45+
done
46+
echo "isJavaFilesChanged=${isJavaFilesChanged}" >> $GITHUB_OUTPUT
47+
echo "isJavaFilesChanged: ${isJavaFilesChanged}"
48+
49+
build:
50+
needs: [findChangedJavaFiles]
51+
if: ${{ needs.findChangedJavaFiles.outputs.isJavaFilesChanged == 'true' }}
52+
runs-on: ubuntu-latest
53+
timeout-minutes: 15
54+
steps:
55+
- uses: actions/checkout@v6
56+
with:
57+
submodules: true
58+
- name: Set up JDK 11
59+
uses: actions/setup-java@v4
60+
with:
61+
java-version: '11'
62+
distribution: 'temurin'
63+
cache: maven
64+
- name: Build with Maven
65+
run: mvn -B compile --file pom.xml
66+
67+
test:
68+
needs: [findChangedJavaFiles, build]
69+
if: ${{ needs.findChangedJavaFiles.outputs.isJavaFilesChanged == 'true' }}
70+
runs-on: ubuntu-latest
71+
timeout-minutes: 15
72+
strategy:
73+
matrix:
74+
java: ['11', '17', '21']
75+
steps:
76+
- uses: actions/checkout@v6
77+
with:
78+
submodules: true
79+
- name: Set up JDK ${{ matrix.java }}
80+
uses: actions/setup-java@v4
81+
with:
82+
java-version: ${{ matrix.java }}
83+
distribution: 'temurin'
84+
cache: maven
85+
- name: Test with Maven
86+
run: mvn -B test --file pom.xml
87+
88+
format:
89+
needs: [findChangedJavaFiles]
90+
if: ${{ needs.findChangedJavaFiles.outputs.isJavaFilesChanged == 'true' }}
91+
runs-on: ubuntu-latest
92+
timeout-minutes: 10
93+
steps:
94+
- uses: actions/checkout@v6
95+
with:
96+
submodules: true
97+
- name: Set up JDK 11
98+
uses: actions/setup-java@v4
99+
with:
100+
java-version: '11'
101+
distribution: 'temurin'
102+
cache: maven
103+
- name: Check formatting with Spotless
104+
run: mvn -B spotless:check --file pom.xml
105+
106+
publishToMavenCentral:
107+
needs: [test, format, findChangedJavaFiles]
108+
if: ${{ needs.findChangedJavaFiles.outputs.isJavaFilesChanged == 'true' && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
109+
runs-on: ubuntu-latest
110+
timeout-minutes: 30
111+
steps:
112+
- uses: actions/checkout@v6
113+
with:
114+
submodules: true
115+
- name: Set up JDK 11
116+
uses: actions/setup-java@v4
117+
with:
118+
java-version: '11'
119+
distribution: 'temurin'
120+
cache: maven
121+
server-id: ossrh
122+
server-username: MAVEN_USERNAME
123+
server-password: MAVEN_PASSWORD
124+
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
125+
gpg-passphrase: MAVEN_GPG_PASSPHRASE
126+
- name: Check if version already published
127+
id: version-check
128+
run: |
129+
PACKAGE_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
130+
PACKAGE_GROUP=$(mvn help:evaluate -Dexpression=project.groupId -q -DforceStdout)
131+
PACKAGE_ARTIFACT=$(mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout)
132+
echo "Package: $PACKAGE_GROUP:$PACKAGE_ARTIFACT:$PACKAGE_VERSION"
133+
134+
# Check if version exists on Maven Central
135+
URL="https://repo1.maven.org/maven2/$(echo $PACKAGE_GROUP | tr '.' '/')/$PACKAGE_ARTIFACT/$PACKAGE_VERSION/"
136+
if curl --head --silent --fail "$URL" > /dev/null 2>&1; then
137+
echo "Version $PACKAGE_VERSION already exists on Maven Central"
138+
echo "should_publish=false" >> $GITHUB_OUTPUT
139+
else
140+
echo "Version $PACKAGE_VERSION does not exist on Maven Central"
141+
echo "should_publish=true" >> $GITHUB_OUTPUT
142+
fi
143+
- name: Publish to Maven Central
144+
if: steps.version-check.outputs.should_publish == 'true'
145+
run: mvn -B deploy -Prelease --file pom.xml
146+
env:
147+
MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
148+
MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
149+
MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
150+
151+
publishRelease:
152+
runs-on: ubuntu-latest
153+
timeout-minutes: 10
154+
needs: [publishToMavenCentral]
155+
if: ${{ needs.findChangedJavaFiles.outputs.isJavaFilesChanged == 'true' && needs.publishToMavenCentral.result == 'success' && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
156+
steps:
157+
- uses: actions/checkout@v6
158+
with:
159+
submodules: true
160+
- name: Set up JDK 11
161+
uses: actions/setup-java@v4
162+
with:
163+
java-version: '11'
164+
distribution: 'temurin'
165+
cache: maven
166+
- name: Check if GitHub release already exists
167+
id: release-check
168+
run: |
169+
PACKAGE_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
170+
TAG_NAME="java_$PACKAGE_VERSION"
171+
echo "Checking if release $TAG_NAME already exists"
172+
173+
# Check if release exists
174+
if gh release view "$TAG_NAME" >/dev/null 2>&1; then
175+
echo "Release $TAG_NAME already exists"
176+
echo "should_create_release=false" >> $GITHUB_OUTPUT
177+
else
178+
echo "Release $TAG_NAME does not exist"
179+
echo "should_create_release=true" >> $GITHUB_OUTPUT
180+
fi
181+
env:
182+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
183+
- name: Create GitHub release
184+
if: steps.release-check.outputs.should_create_release == 'true'
185+
run: |
186+
PACKAGE_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
187+
PACKAGE_GROUP=$(mvn help:evaluate -Dexpression=project.groupId -q -DforceStdout)
188+
PACKAGE_ARTIFACT=$(mvn help:evaluate -Dexpression=project.artifactId -q -DforceStdout)
189+
190+
# Create release with consistent tag format: java_version
191+
gh release create "java_${PACKAGE_VERSION}" \
192+
--title "[Java] $PACKAGE_VERSION" \
193+
--notes "https://central.sonatype.com/artifact/$PACKAGE_GROUP/$PACKAGE_ARTIFACT/$PACKAGE_VERSION"
194+
env:
195+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,3 +337,6 @@ rust/target/
337337
target/venv/
338338
.venv/
339339
venv/
340+
341+
# java
342+
java/target/

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
| [![Actions Status](https://github.com/link-foundation/links-notation/workflows/rust/badge.svg)](https://github.com/link-foundation/links-notation/actions?workflow=rust) | [![Crates.io Version and Downloads count](https://img.shields.io/crates/v/links-notation?label=crates.io&style=flat)](https://crates.io/crates/links-notation) | **[Rust](rust/README.md)** |
66
| [![Actions Status](https://github.com/link-foundation/links-notation/workflows/csharp/badge.svg)](https://github.com/link-foundation/links-notation/actions?workflow=csharp) | [![NuGet Version and Downloads count](https://img.shields.io/nuget/v/Link.Foundation.Links.Notation?label=nuget&style=flat)](https://www.nuget.org/packages/Link.Foundation.Links.Notation) | **[C#](csharp/README.md)** |
77
| [![Actions Status](https://github.com/link-foundation/links-notation/workflows/python/badge.svg)](https://github.com/link-foundation/links-notation/actions?workflow=python) | [![PyPI Version and Downloads count](https://img.shields.io/pypi/v/links-notation?label=pypi&style=flat)](https://pypi.org/project/links-notation/) | **[Python](python/README.md)** |
8+
| [![Actions Status](https://github.com/link-foundation/links-notation/workflows/java/badge.svg)](https://github.com/link-foundation/links-notation/actions?workflow=java) | [![Maven Central Version](https://img.shields.io/maven-central/v/io.github.link-foundation/links-notation?label=maven&style=flat)](https://central.sonatype.com/artifact/io.github.link-foundation/links-notation) | **[Java](java/README.md)** |
89

910
[![Gitpod](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/link-foundation/links-notation)
1011
[![Open in GitHub Codespaces](https://img.shields.io/badge/GitHub%20Codespaces-Open-181717?logo=github)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=link-foundation/links-notation)
@@ -56,6 +57,14 @@ parser = Parser()
5657
links = parser.parse("papa (lovesMama: loves mama)")
5758
```
5859

60+
### Java
61+
62+
```java
63+
import io.github.linkfoundation.linksnotation.Parser;
64+
Parser parser = new Parser();
65+
List<Link> links = parser.parse("papa (lovesMama: loves mama)");
66+
```
67+
5968
## Examples
6069

6170
### Links notation (lino)
@@ -137,23 +146,25 @@ language-specific documentation:
137146
- **[JavaScript README](js/README.md)** - Modern web development guide
138147
- **[Rust README](rust/README.md)** - High-performance parsing guide
139148
- **[Python README](python/README.md)** - Python package guide
149+
- **[Java README](java/README.md)** - Java/Maven package guide
140150

141151
Additional resources:
142152

143-
- [Test Case Comparison](TEST_CASE_COMPARISON.md) - Comprehensive test coverage comparison across all 4 language implementations
153+
- [Test Case Comparison](TEST_CASE_COMPARISON.md) - Comprehensive test coverage comparison across language implementations
144154
- [PDF Documentation](https://link-foundation.github.io/links-notation/csharp/Link.Foundation.Links.Notation.pdf)
145155
\- Complete reference for offline reading
146156
- [Links Theory 0.0.2](https://habr.com/en/articles/895896) - Theoretical
147157
foundation that Links Notation fully supports
148158

149159
## Test Coverage & Implementation Parity
150160

151-
All four language implementations (C#, JavaScript, Rust, Python) maintain **equivalent core functionality** with comprehensive test coverage:
161+
All five language implementations (C#, JavaScript, Rust, Python, Java) maintain **equivalent core functionality** with comprehensive test coverage:
152162

153163
- **Python**: 108 tests across 10 categories - All passing ✅
154164
- **JavaScript**: 109 tests across 11 categories - All passing ✅
155165
- **Rust**: 110 tests across 11 categories - All passing ✅
156166
- **C#**: 111 tests across 12 categories - All passing ✅
167+
- **Java**: 117 tests across 7 categories - All passing ✅
157168

158169
**90+ tests match identically** across all languages, verifying functional equivalence. See [TEST_CASE_COMPARISON.md](TEST_CASE_COMPARISON.md) for the complete cross-language test comparison with links to source code.
159170

README.ru.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
| [![Состояние Actions](https://github.com/link-foundation/links-notation/workflows/rust/badge.svg)](https://github.com/link-foundation/links-notation/actions?workflow=rust) | [![Версия Crates.io и количество загрузок](https://img.shields.io/crates/v/links-notation?label=crates.io&style=flat)](https://crates.io/crates/links-notation) | **[Rust](rust/README.ru.md)** |
66
| [![Состояние Actions](https://github.com/link-foundation/links-notation/workflows/csharp/badge.svg)](https://github.com/link-foundation/links-notation/actions?workflow=csharp) | [![Версия NuGet пакета и количество загрузок](https://img.shields.io/nuget/v/Link.Foundation.Links.Notation?label=nuget&style=flat)](https://www.nuget.org/packages/Link.Foundation.Links.Notation) | **[C#](csharp/README.ru.md)** |
77
| [![Состояние Actions](https://github.com/link-foundation/links-notation/workflows/python/badge.svg)](https://github.com/link-foundation/links-notation/actions?workflow=python) | [![Версия PyPI и количество загрузок](https://img.shields.io/pypi/v/links-notation?label=pypi&style=flat)](https://pypi.org/project/links-notation/) | **[Python](python/README.ru.md)** |
8+
| [![Состояние Actions](https://github.com/link-foundation/links-notation/workflows/java/badge.svg)](https://github.com/link-foundation/links-notation/actions?workflow=java) | [![Версия Maven Central](https://img.shields.io/maven-central/v/io.github.link-foundation/links-notation?label=maven&style=flat)](https://central.sonatype.com/artifact/io.github.link-foundation/links-notation) | **[Java](java/README.ru.md)** |
89

910
[![Gitpod](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/link-foundation/links-notation)
1011
[![Open in GitHub Codespaces](https://img.shields.io/badge/GitHub%20Codespaces-Open-181717?logo=github)](https://github.com/codespaces/new?hide_repo_select=true&ref=main&repo=link-foundation/links-notation)
@@ -56,6 +57,14 @@ parser = Parser()
5657
links = parser.parse("папа (любитМаму: любит маму)")
5758
```
5859

60+
### Java
61+
62+
```java
63+
import io.github.linkfoundation.linksnotation.Parser;
64+
Parser parser = new Parser();
65+
List<Link> links = parser.parse("папа (любитМаму: любит маму)");
66+
```
67+
5968
## Примеры
6069

6170
### Нотация связей
@@ -123,6 +132,7 @@ links = parser.parse("папа (любитМаму: любит маму)")
123132
- **[README Rust](rust/README.ru.md)** - Руководство по
124133
высокопроизводительному парсингу
125134
- **[README Python](python/README.ru.md)** - Руководство по работе с пакетом Python
135+
- **[README Java](java/README.ru.md)** - Руководство по работе с пакетом Java/Maven
126136

127137
Дополнительные ресурсы:
128138

0 commit comments

Comments
 (0)