Skip to content

Commit

Permalink
Refactor router
Browse files Browse the repository at this point in the history
  • Loading branch information
hpehl committed May 4, 2024
1 parent 8ac45c5 commit bcb6147
Show file tree
Hide file tree
Showing 30 changed files with 1,154 additions and 283 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Add support for routes with parameters: `/contacts/:contactId`
- Add asynchronous loaders for places
- Add place(s) builder API and nested places

### Changed

- Optimize logging implementation

## [1.4.12] - 2024-04-30

### Added
Expand Down
22 changes: 19 additions & 3 deletions logger/src/main/java/org/jboss/elemento/logger/Category.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
*/
package org.jboss.elemento.logger;

import java.util.Arrays;

import static java.lang.Math.abs;
import static java.util.Arrays.fill;

class Category {

Expand All @@ -30,6 +29,23 @@ static String parent(String category) {
return "";
}

static boolean isSubcategory(String parent, String child) {
if (parent != null && child != null && !parent.isEmpty() && child.contains(".")) {
String[] parentParts = parent.split("\\.");
String[] childParts = child.split("\\.");
if (parentParts.length >= childParts.length) {
return false;
}
for (int i = 0; i < parentParts.length; i++) {
if (!parentParts[i].equals(childParts[i])) {
return false;
}
}
return true;
}
return false;
}

static String format(String category, int length) {
if (category == null || category.trim().isEmpty()) {
return rightPad(NONE, length);
Expand All @@ -53,7 +69,7 @@ private static String rightPad(String value, int length) {
return value.substring(diff);
} else {
byte[] bytes = new byte[abs(diff)];
Arrays.fill(bytes, (byte) ' ');
fill(bytes, (byte) ' ');
return new String(bytes) + value;
}
}
Expand Down
51 changes: 51 additions & 0 deletions logger/src/main/java/org/jboss/elemento/logger/LevelOverrides.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright 2023 Red Hat
*
* 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
*
* https://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.
*/
package org.jboss.elemento.logger;

import java.util.HashMap;
import java.util.Map;

class LevelOverrides {

final Map<String, Level> levels;

LevelOverrides() {
levels = new HashMap<>() {};
}

void addLevel(String category, Level level) {
levels.put(category, level);
}

void removeLevel(String category) {
levels.remove(category);
}

Level overriddenLevel(String category) {
int length = 0;
Level level = null;
for (Map.Entry<String, Level> entry : levels.entrySet()) {
String parent = entry.getKey();
if (Category.isSubcategory(parent, category)) {
if (parent.length() > length) {
level = entry.getValue();
length = parent.length();
}
}
}
return level;
}
}
50 changes: 25 additions & 25 deletions logger/src/main/java/org/jboss/elemento/logger/Logger.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ public class Logger {
private static final int CATEGORY_LENGTH = 23;
private static final String ROOT_CATEGORY = "root";
private static final Logger ROOT_LOGGER = new Logger(ROOT_CATEGORY);
private static final Map<String, Logger> loggers = new HashMap<>();

// package local to enable unit tests
static final Map<String, Level> levels = new HashMap<>();
// package local because of unit tests
static final Map<String, Logger> loggers = new HashMap<>();
static final LevelOverrides levelOverrides = new LevelOverrides();
static Level level = DEFAULT_LEVEL;

static {
Expand All @@ -83,15 +83,16 @@ public class Logger {

// ------------------------------------------------------ static API

public static Logger getLogger(String name) {
public static Logger getLogger(String category) {
Logger logger;
if (name == null || name.isEmpty()) {
if (category == null || category.isEmpty()) {
logger = ROOT_LOGGER;
} else {
logger = loggers.get(name);
logger = loggers.get(category);
if (logger == null) {
logger = new Logger(name);
loggers.put(name, logger);
logger = new Logger(category);
loggers.put(category, logger);
applyOverrides();
}
}
return logger;
Expand All @@ -103,13 +104,15 @@ public static void setLevel(Level level) {
}

public static void setLevel(String category, Level level) {
levels.put(category, level);
levelOverrides.addLevel(category, level);
applyOverrides();
console.info("Set log level for %s to %s", category, level.name());
}

@JsMethod
public static void resetLevel(String category) {
levels.remove(category);
levelOverrides.removeLevel(category);
applyOverrides();
console.info("Log level for %s has been reset to global log level (%s)", category, Logger.level.name());
}

Expand All @@ -132,14 +135,22 @@ private static void jsSetLevel(String category, String level) {
}
}

private static void applyOverrides() {
for (Map.Entry<String, Logger> entry : loggers.entrySet()) {
String category = entry.getKey();
Logger logger = entry.getValue();
logger.customLevel = levelOverrides.overriddenLevel(category);
}
}

// ------------------------------------------------------ instance

private final String category;
private final String formattedCategory;
private Level customLevel;

private Logger(String category) {
this.category = category;
this.formattedCategory = Category.format(category, CATEGORY_LENGTH);
this.customLevel = null;
}

// ------------------------------------------------------ log methods
Expand Down Expand Up @@ -253,19 +264,8 @@ public void error(String message, Object... params) {
// ------------------------------------------------------ internal

boolean shouldLog(Level level) {
boolean global = Logger.level.ordinal() >= level.ordinal();
if (!Logger.levels.isEmpty()) {
String cc = category;
Level cLevel = Logger.levels.get(cc);
while (cLevel == null && !cc.isEmpty()) {
cc = Category.parent(cc);
cLevel = Logger.levels.get(cc);
}
if (cLevel != null) {
return cLevel.ordinal() >= level.ordinal();
}
}
return global;
Level effectiveLevel = customLevel != null ? customLevel : Logger.level;
return effectiveLevel.ordinal() >= level.ordinal();
}

private String format(Level level, String message) {
Expand Down
57 changes: 43 additions & 14 deletions logger/src/test/java/org/jboss/elemento/logger/CategoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,67 @@
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

class CategoryTest {

@Test
void blank() {
void parent() {
assertEquals("", Category.parent(null));
assertEquals("", Category.parent(""));
assertEquals("", Category.parent("Foo"));
assertEquals("a", Category.parent("a."));
assertEquals("a.b.c", Category.parent("a.b.c.Foo"));
assertEquals("a.b", Category.parent("a.b.c"));
assertEquals("a", Category.parent("a.b"));
}

@Test
void isSubcategory() {
assertTrue(Category.isSubcategory("a.b.c", "a.b.c.Foo"));
assertTrue(Category.isSubcategory("a.b", "a.b.c.Foo"));
assertTrue(Category.isSubcategory(" .", " . "));

assertFalse(Category.isSubcategory(null, null));
assertFalse(Category.isSubcategory(null, ""));
assertFalse(Category.isSubcategory("", null));
assertFalse(Category.isSubcategory("", ""));
assertFalse(Category.isSubcategory("", ". "));
assertFalse(Category.isSubcategory(".", "."));
assertFalse(Category.isSubcategory(".", ".."));
assertFalse(Category.isSubcategory("a.", "a."));
assertFalse(Category.isSubcategory(".a", ".a"));
assertFalse(Category.isSubcategory(".a.", ".a."));
assertFalse(Category.isSubcategory("a.", "b."));
assertFalse(Category.isSubcategory(".a", ".b"));
assertFalse(Category.isSubcategory(".a.", ".b."));
assertFalse(Category.isSubcategory("Foo", "Bar"));
assertFalse(Category.isSubcategory("a.b.c", "Bar"));
assertFalse(Category.isSubcategory("a.b.c.Foo", "a.b.c"));
assertFalse(Category.isSubcategory("a.b.c.Foo", "a.b"));
assertFalse(Category.isSubcategory("a.b.c.Foo", "x.y.z.Bar"));
assertFalse(Category.isSubcategory("F.o.o", "B.a.r"));
}

@Test
void formatBlank() {
assertEquals(" <none>", Category.format(null, 10));
assertEquals(" <none>", Category.format("", 10));
assertEquals(" <none>", Category.format(" ", 10));
assertEquals(" <none>", Category.format(" ", 10));
}

@Test
void simple() {
void formatSimple() {
assertEquals(" foo", Category.format("foo", 10));
assertEquals("1234567890", Category.format("1234567890", 10));
assertEquals("characters", Category.format("more than 10 characters", 10));
}

@Test
void fqcn() {
void FormatNested() {
assertEquals(" a.b.c.Foo", Category.format("a.b.c.Foo", 15));
assertEquals(".j.e.l.Category", Category.format("org.jboss.elemento.logger.Category", 15));
}

@Test
void parent() {
assertEquals("", Category.parent(null));
assertEquals("", Category.parent(""));
assertEquals("", Category.parent("Foo"));
assertEquals("a", Category.parent("a."));
assertEquals("a.b.c", Category.parent("a.b.c.Foo"));
assertEquals("a.b", Category.parent("a.b.c"));
assertEquals("a", Category.parent("a.b"));
}
}
Loading

0 comments on commit bcb6147

Please sign in to comment.