# Eo / Common / Util

## Overview

The `eo.common.util` package provides a collection of lightweight string utility methods centered around a single class, [`JKKStringUtil`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java). It exists to centralize common null-safety and string manipulation patterns — checking whether a string is null or blank, converting nulls to safe defaults, and truncating strings by byte length while respecting multi-byte character boundaries. This is especially relevant in a Japanese enterprise context where half-width and full-width CJK characters require byte-aware handling.

## Module Structure

```
eo.common.util
└── JKKStringUtil    (string utility class, 7 static methods)
```

**Module statistics**

| Metric | Value |
|--------|-------|
| Source files | 1 |
| Classes | 1 |
| Methods | 7 (all static) |

## Key Classes

### JKKStringUtil

**[`JKKStringUtil`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:28)** is the sole class in this package. It is a classic utility class — all members are `static`, the class has no explicit constructor (relies on the default), and no fields are defined. It was created in 2012 as part of the K-Opticom eo customer base system.

The methods fall into three logical categories:

#### Validation methods

- **[`isNullBlank(String str)`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:36)** — Returns `true` if the string is `null` or an empty string (`""`). Does not trim whitespace. This is the most basic null-or-blank check in the class.

- **[`isNullSpace(String str)`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:51)** — Returns `true` if the string is `null` or consists only of whitespace (after trimming). Unlike `isNullBlank`, this catches strings that contain only spaces.

- **[`isNullEmpty(Object target)`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:144)** — The most general check in the class. Returns `true` if the target is `null`, an empty string (`""`), or an empty `ArrayList`. This appears to be a convenience method for form or data validation where any of those "empty" states should be treated equivalently.

#### Conversion methods

- **[`nullToBlank(String str)`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:66)** — Returns the input string unchanged if non-null; returns `""` (empty string) if the input is `null`. This is a null-coalescing helper — useful when a downstream method cannot accept null.

- **[`nullToSpace(String str)`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:81)** — Returns the input string unchanged if non-null; returns `" "` (a single space) if the input is `null`. This is useful when an empty string would cause formatting issues (e.g., visual rendering).

- **[`nullBlankToSpace(String str)`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:96)** — Combines the logic of `isNullBlank` and `nullToSpace`: returns `" "` if the input is `null` or empty, otherwise returns the input unchanged. A natural composition of the two methods above.

#### Transform methods

- **[`subStringByte(String str, int len)`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:113)** — Truncates a string to a specified byte length (`len`). Unlike `substring`, which counts characters, this method counts bytes by inspecting each character:
  - ASCII characters (code point <= `0x7E`), backslash (`0x00A5`), tilde (`0x203E`), and half-width Katakana (`0xFF61`–`0xFF9F`) are counted as **1 byte**.
  - All other characters (full-width CJK, full-width Katakana, etc.) are counted as **2 bytes**.
  - If the input length exceeds `len`, it returns the substring up to (but not exceeding) the byte limit. If the input fits within `len`, it returns the original string.

  This method is critical for systems with fixed-width database columns or display fields where the byte limit is enforced rather than the character count. The implementation avoids allocating a `byte[]` by counting byte length during iteration.

#### Method overview

```
flowchart LR
    PKG["eo.common.util"] --> CLS["JKKStringUtil"]
    CLS --> M1["isNullBlank"]
    CLS --> M2["isNullSpace"]
    CLS --> M3["nullToBlank"]
    CLS --> M4["nullToSpace"]
    CLS --> M5["nullBlankToSpace"]
    CLS --> M6["subStringByte"]
    CLS --> M7["isNullEmpty"]
```

#### Validation and conversion flow

```
flowchart TD
    subgraph CHECKS["Validation Methods"]
        M1["isNullBlank: null or empty"]
        M2["isNullSpace: null or whitespace"]
        M7["isNullEmpty: null, empty String, or empty ArrayList"]
    end

    subgraph CONVERSIONS["Conversion Methods"]
        M3["nullToBlank: null -> empty string"]
        M4["nullToSpace: null -> single space"]
        M5["nullBlankToSpace: null/empty -> space"]
    end

    subgraph TRANSFORMS["Transform Methods"]
        M6["subStringByte: truncate by byte length"]
    end
```

## How It Works

### The `subStringByte` algorithm

This is the most algorithmically interesting method in the class. Here's the step-by-step logic:

1. Iterate through the string character by character.
2. For each character, classify it as single-byte or double-byte using Unicode range checks:
   - `c <= 0x007E` → single-byte (ASCII letters, digits, punctuation)
   - `c == 0x00A5` → single-byte (YEN sign, treated as single-byte in Shift_JIS)
   - `c == 0x203E` → single-byte (OVERLINE, treated as single-byte in Shift_JIS)
   - `0xFF61 <= c <= 0xFF9F` → single-byte (half-width Katakana)
   - All others → double-byte (full-width, CJK, etc.)
3. Accumulate the running byte count. Once the count would exceed `len`, return `str.substring(0, i)` — the characters before the one that would overflow.
4. If the loop completes without exceeding `len`, return the original string unchanged.

**Key design decision:** The method operates directly on `String` code points rather than converting to a `byte[]`. This avoids an intermediate encoding step (e.g., `getBytes("Shift_JIS")`), which could be locale-dependent or throw `UnsupportedEncodingException`. However, the byte-width classification is a simplified approximation of Shift_JIS encoding — it assumes all non-ASCII characters are 2 bytes, which is correct for the Japanese Shift_JIS character set but may not generalize to other encodings.

### Design patterns

- **Utility class pattern**: All methods are `static`, no state is maintained, and no public constructor exists. The class is not declared `final`, which means it can be subclassed, but doing so would be semantically unusual.
- **Null-safety focus**: Almost every method is designed to handle `null` inputs gracefully — either returning a safe default value or a boolean indicating the null/empty state. This reflects the needs of enterprise forms and data processing where nullable fields are common.

## Data Model

This module does not define any data model classes (entities, DTOs, or records). It operates entirely on `String` and `Object` inputs, producing either `boolean` or `String` outputs.

The only external type referenced is `java.util.ArrayList`, used in [`isNullEmpty`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:144) to check for empty lists in a generic validation context.

## Dependencies and Integration

This module has no external dependencies beyond the Java standard library (`java.util.ArrayList`). It does not depend on any other modules in the `eo.common.util` package (there are none) and no cross-module relationships are detected.

It is a leaf utility module — other modules in the system likely call these methods directly from business logic or form handlers.

## Notes for Developers

- **Not a replacement for Apache Commons `StringUtils`**: This class provides a minimal, purpose-built set of utilities. If the project already has a broader string utility library (e.g., Apache Commons Lang's `StringUtils`), consider whether `JKKStringUtil` can be retired or migrated.

- **`subStringByte` is encoding-specific**: The byte-width classification in [`subStringByte`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:113) is tailored for Shift_JIS (Japanese Windows encoding). For UTF-8 environments, double-byte characters may encode as 3 bytes, making this method underestimate the true byte length. Verify the encoding assumptions before reusing in new contexts.

- **`isNullEmpty` accepts any `Object`**: The [`isNullEmpty`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:144) method uses `instanceof` checks for `String` and `ArrayList`. It will silently return `false` for any type it doesn't recognize (including `List`, `Collection`, `Map`, or arrays). If the intent is broad emptiness checking, this is a potential bug — callers should prefer checking with the specific collection type they actually hold.

- **The class name includes "JKK"**: The `JKK` prefix likely refers to a specific project or subsystem within the K-Opticom eo system (possibly "Japan Key Customers"). This naming convention may appear in other classes throughout the codebase.

- **Japanese comments**: The source code comments and the class-level Javadoc are written in Japanese. The original author is 富士通 (Fujitsu), and the class was created on 2012-07-19.

- **`@SuppressWarnings("unchecked")`**: The [`isNullEmpty`](input_sample_sourcecode/Source/koptCommon/src/eo/common/util/JKKStringUtil.java:144) method suppresses unchecked warnings because it casts `target` to `ArrayList` via `instanceof`. In modern Java, this is typically handled automatically, so this suppression suggests the code was written for an older Java version.
