Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/spotless.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Code Formatting & Style Check

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
check-formatting:
name: Run spotless and checkstyle
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'

- name: Cache gradle dependencies
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle.kts', '**/gradle-wrapper.properties') }}
restore-keys: gradle-${{ runner.os }}-

- name: Change execute permission
run: chmod +x gradlew

- name: Run spotless
run: ./gradlew spotlessCheck

- name: Run checkstyle
run: ./gradlew checkstyleMain checkstyleTest
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.idea
.gradle
.vscode
*.iml
.editorconfig
build
29 changes: 25 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ plugins {
java
id("org.springframework.boot") version "3.4.3"
id("io.spring.dependency-management") version "1.1.7"
id("checkstyle")
id("com.diffplug.spotless") version "6.25.0"
}

group = "com.m"
version = "0.0.1-SNAPSHOT"
version = "0.0.2"

java {
toolchain {
Expand All @@ -19,6 +21,21 @@ configurations {
}
}

spotless {
java {
indentWithTabs(4)
indentWithSpaces(4)
endWithNewline()
trimTrailingWhitespace()
removeUnusedImports()
}
}

checkstyle {
toolVersion = "10.15.0"
configFile = rootProject.file("config/checkstyle/checkstyle.xml")
}

repositories {
mavenCentral()
}
Expand All @@ -34,6 +51,10 @@ dependencies {
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}

tasks.withType<Test> {
useJUnitPlatform()
}

tasks.withType<Checkstyle>().configureEach {
reports {
html.required.set(true)
xml.required.set(false)
}
}
11 changes: 11 additions & 0 deletions config/checkstyle/checkstyle.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"https://checkstyle.org/dtds/configuration_1_3.dtd">

<module name="Checker">
<module name="TreeWalker">
<module name="WhitespaceAround"/>
<module name="MethodParamPad"/>
</module>
</module>
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
2 changes: 1 addition & 1 deletion gradlew
100644 → 100755

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions src/main/java/com/m/linshor/LinShorApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@

@SpringBootApplication
public class LinShorApplication {

public static void main(String[] args) {
SpringApplication.run(LinShorApplication.class, args);
}

}
58 changes: 58 additions & 0 deletions src/main/java/com/m/linshor/controllers/LinShorController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.m.linshor.controllers;

import com.m.linshor.entities.Mapping;
import com.m.linshor.services.LinShorService;

import java.net.URI;
import java.util.Optional;

import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/linshor/v1")
@AllArgsConstructor
public class LinShorController {
private final LinShorService linShorService;

@GetMapping("/find/{shortUrl}")
public Optional<Mapping> findByShortUrl(@PathVariable String shortUrl) {
return linShorService.findByShortUrl(shortUrl);
}

@PostMapping("post")
public Mapping saveLink(String longUrl) {
return linShorService.saveLink(longUrl);
}

@GetMapping("/{id}")
public Optional<Mapping> findById(@PathVariable int id) {
return linShorService.findById(id);
}

@PutMapping("update")
public Mapping updateLink(String longUrl) {
return linShorService.updateLink(longUrl);
}

@DeleteMapping("delete/{id}")
public int deleteById(@PathVariable int id) {
linShorService.deleteById(id);
return 200;
}

@PostMapping("/shortener")
public ResponseEntity<String> linshorUrl(@RequestBody String longUrl) {
Mapping mapping = linShorService.saveLink(longUrl);
return ResponseEntity.ok(mapping.getShortUrl());
}

@GetMapping("/{shortUrl}")
public ResponseEntity<Object> redirectToLongUrl(@PathVariable String shortUrl) {
Optional<Mapping> mapping = linShorService.findByShortUrl(shortUrl);
return mapping
.map(m -> ResponseEntity.status(302).location(URI.create(m.getLongUrl())).build())
.orElseGet(() -> ResponseEntity.notFound().build());
}
}
21 changes: 21 additions & 0 deletions src/main/java/com/m/linshor/entities/Mapping.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.m.linshor.entities;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.*;

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Entity
public class Mapping {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
int id;

String longUrl;
String shortUrl;
}
61 changes: 61 additions & 0 deletions src/main/java/com/m/linshor/repositories/MappingDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.m.linshor.repositories;

import com.m.linshor.entities.Mapping;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;

import org.springframework.stereotype.Repository;

@Repository
public class MappingDao {
private final List<Mapping> LINKS = new ArrayList<>();

public Mapping saveLink(Mapping mapping) {
LINKS.add(mapping);
return null;
}

public Optional<Mapping> findByShortUrl(String shortUrl) {
return LINKS.stream().filter(link -> link.getShortUrl().equals(shortUrl)).findFirst();
}

public Optional<Mapping> findById(int id) {
return LINKS.stream().filter(element -> element.getId() == id).findFirst();
}

public Mapping updateLink(Mapping mapping) {
var linkIndex =
IntStream.range(0, LINKS.size())
.filter(index -> LINKS.get(index).getId() == mapping.getId())
.findFirst()
.orElse(-1);
if (linkIndex > -1) {
LINKS.set(linkIndex, mapping);
return mapping;
}
return null;
}

public void deleteById(int id) {
var link = findById(id);
if (link.isPresent()) {
LINKS.remove(link);
}
}

public Mapping findByLongUrl(String longUrl) {
var linkIndex =
IntStream.range(0, LINKS.size())
.filter(index -> LINKS.get(index).getLongUrl().equals(longUrl))
.findFirst()
.orElse(-1);
if (linkIndex > -1) {
return LINKS.get(linkIndex);
} else {
return null;
}
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/m/linshor/repositories/MappingRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.m.linshor.repositories;

import com.m.linshor.entities.Mapping;

import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MappingRepository extends JpaRepository<Mapping, Long> {
Optional<Mapping> findByShortUrl(String shortUrl);

Optional<Mapping> findById(int id);

Mapping findByLongUrl(String longUrl);
}
70 changes: 70 additions & 0 deletions src/main/java/com/m/linshor/services/InMemoryLinShorService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.m.linshor.services;

import com.m.linshor.entities.Mapping;
import com.m.linshor.repositories.MappingDao;

import java.util.Optional;
import java.util.Random;

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@AllArgsConstructor
public class InMemoryLinShorService implements LinShorService {
private MappingDao repository;
private static final String BASE62 =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
private static final int SHORT_URL_LENGTH = 10;

@Override
public Optional<Mapping> findByShortUrl(String shortUrl) {
return repository.findByShortUrl(shortUrl);
}

@Override
public Mapping saveLink(String longUrl) {
String shortUrl;
do {
shortUrl = generateShor();
} while (repository.findByShortUrl(shortUrl).isPresent());

Mapping urlMapping = new Mapping();
urlMapping.setShortUrl(shortUrl);
urlMapping.setLongUrl(longUrl);
return repository.saveLink(urlMapping);
}

@Override
public Optional<Mapping> findById(int id) {
return repository.findById(id);
}

@Override
public Mapping updateLink(String longUrl) {
Mapping mapping = findByLongUrl(longUrl);
String shortUrl = generateShor();

mapping.setShortUrl(shortUrl);
return repository.updateLink(mapping);
}

@Override
public void deleteById(int id) {
repository.deleteById(id);
}

private String generateShor() {
Random random = new Random();
StringBuilder sb = new StringBuilder(SHORT_URL_LENGTH);
for (int i = 0; i < SHORT_URL_LENGTH; i++) {
sb.append(BASE62.charAt(random.nextInt(BASE62.length())));
}
return sb.toString();
}

@Override
public Mapping findByLongUrl(String longUrl) {
return repository.findByLongUrl(longUrl);
}
}
23 changes: 23 additions & 0 deletions src/main/java/com/m/linshor/services/LinShorService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.m.linshor.services;

import com.m.linshor.entities.Mapping;

import java.util.Optional;

import org.springframework.stereotype.Service;

@Service
public interface LinShorService {

Optional<Mapping> findByShortUrl(String shortUrl);

Mapping saveLink(String longUrl);

Optional<Mapping> findById(int id);

Mapping updateLink(String longUrl);

void deleteById(int id);

Mapping findByLongUrl(String longUrl);
}
Loading