Skip to main content

IccCodeConnectBookClient Implementation Plan

Issue: #339 - ICC Code Connect API Client

Goal

Create IccCodeConnectBookClient in the codeconnect package to recursively fetch ICC Code Connect books using the existing retriever classes, persisting files in api/api.iccsafe.org.

Proposed Changes

Phase 1: Content Persister

[NEW] IccCodeConnectContentPersister.java

Persist individual content items:

public void fetchAndSaveContent(String contentId, String outputPath)

Phase 2: Section Fetcher

[NEW] IccCodeConnectSectionFetcher.java

Recursively fetch section and its content items:

public SectionList fetchSection(String bookId, String chapterId, String sectionId)
public void fetchSectionWithContent(String bookId, String chapterId, String sectionId)

Phase 3: Chapter Fetcher

[NEW] IccCodeConnectChapterFetcher.java

Fetch chapter metadata and all its sections:

public ChapterList fetchChapter(String bookId, String chapterId)
public void fetchChapterWithSections(String bookId, String chapterId)

Phase 4: Book Client

[NEW] IccCodeConnectBookClient.java

Full book fetch - Builder pattern like IccBookClient:

public class IccCodeConnectBookClient {
private final String bookId;
private final FileSystemHandler fsHandler;
private final IccCodeConnectClient client;

public void fetch() // Full book fetch
public void fetchBookInfo()
public void fetchChaptersIndex()
public void fetchAllChapters() // With rate limiting
}

Folder Structure

api/api.iccsafe.org/
├── v1/
│ ├── books.json # All books
│ ├── book/{bookId}/
│ │ ├── chapters.json # Chapter list
│ │ └── chapter/{chapterId}/
│ │ ├── sections.json # Section list
│ │ └── list/{sectionId}.json
│ └── content/{contentId}.json

Verification Plan

  1. Unit test each component independently
  2. Integration test: fetch a single content item
  3. Integration test: fetch a single section with content
  4. Integration test: fetch a single chapter with sections
  5. Full book fetch with rate limiting (manual verification)

API Nuances and Gotchas

Empty Section IDs (Definitions) vs Regular Sections

The API sections list contains mixed types of items:

  1. Regular Sections: Have dtype="section" and a valid id. These are traversable and have content.
  2. Definitions/Markers: Have dtype="definition" (or potentially other types) and an empty id. These are typically inline text markers or metadata without their own content endpoint.

Trying to fetch content for items with empty IDs results in a 404. Resolution: The recursive fetcher MUST skip items where id is empty.

Example Payload Comparison:

{
"sections": [
{
"id": "IBC2018P6_Ch04_Sec402.8.2.1",
"dtype": "section", // VALID: Has ID and dtype="section"
"title": "Occupant formula"
},
{
"dtype": "definition", // INVALID: No ID, dtype="definition"
"childrenCount": { "subsections": 0 }
}
]
}

In the above example, the first item is processed. The second item (definition) is ignored.