Skip to content
Draft
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
111 changes: 111 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Registry Loader is a NASA Planetary Data System (PDS) toolset for loading data into the PDS Registry (Elasticsearch/OpenSearch-based). It combines three Maven modules into a single multi-module project:

- **common** (`registry-common`) - Shared library for Elasticsearch/OpenSearch connectivity, metadata extraction, and data dictionary operations
- **harvest** - CLI tool that crawls file systems to discover PDS4 products and indexes metadata into the Registry
- **manager** (`registry-manager`) - CLI tool for managing the Registry: creating indices, loading data dictionaries, setting archive status, and data operations

## Build Commands

```bash
# Build all modules
mvn package

# Build specific module
mvn -pl common package
mvn -pl harvest package
mvn -pl manager package

# Run tests
mvn test

# Run single test class
mvn -pl common test -Dtest=TestBulkResponseParser

# Skip tests
mvn package -DskipTests

# Clean build
mvn clean package

# Install to local repository
mvn install

# Deploy release (requires GPG setup)
mvn -P release clean deploy
```

## Running the Tools

After building, executable JARs are in `{module}/target/`:

```bash
# Harvest - requires config file
java -jar harvest/target/harvest-*.jar -c <config.xml>

# Registry Manager - various subcommands
java -jar manager/target/registry-manager-*.jar <command> <options>

# Registry Manager commands:
# create-registry, delete-registry
# list-dd, load-dd, delete-dd, export-dd, upgrade-dd
# delete-data, export-file, set-archive-status, update-alt-ids
```

## Architecture

### Module Dependencies
```
harvest ──────┐
├──> common ──> Elasticsearch/OpenSearch
manager ──────┘
```

### Key Packages

**common** (`gov.nasa.pds.registry.common`):
- `connection/` - Registry connection handling (AWS OpenSearch Serverless, direct ES/OS)
- `connection/aws/` - AWS-specific implementations using OpenSearch SDK
- `connection/es/` - Standard Elasticsearch REST client implementations
- `es/dao/` - Data Access Objects for registry operations
- `es/service/` - High-level services (schema updates, data loading)
- `meta/` - Metadata extractors for PDS4 labels
- `dd/` - Data dictionary parsing and loading

**harvest** (`gov.nasa.pds.harvest`):
- `HarvestCli` - CLI entry point
- `cmd/` - Command implementations
- `cfg/` - Configuration parsing

**manager** (`gov.nasa.pds.registry.mgr`):
- `RegistryManagerCli` - CLI entry point with command dispatcher
- `cmd/reg/` - Registry management commands
- `cmd/dd/` - Data dictionary commands
- `cmd/data/` - Data manipulation commands

### Connection Configuration

Registry connections use XML configuration files. The `common` module provides:
- Direct connections to Elasticsearch/OpenSearch
- AWS OpenSearch Serverless with Cognito authentication
- Connection factory pattern via `EstablishConnectionFactory`

## Docker

Build Docker image containing both tools:
```bash
docker image build -t nasapds/registry-loader -f docker/Dockerfile \
--build-arg harvest_package_path=harvest/target/harvest-*-bin.tar.gz \
--build-arg reg_manager_package_path=manager/target/registry-manager-*-bin.tar.gz .
```

## CI/CD

- Releases triggered by pushing `release/*` tags
- Uses NASA-PDS Roundup Action for automated releases
- Docker images published to Docker Hub on stable releases
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
Expand Down Expand Up @@ -36,43 +37,72 @@
}
/**
* Set archive status
* @param lidvid ID of a product to update. If it is a collection,
* update primary references from collection inventory.
* @param lidvid LID or LIDVID of a product to update. If a bare LID is provided it is
* resolved to the latest LIDVID. If the product is a collection, primary references from
* collection inventory are also updated. If it is a bundle, all referenced collections and
* their products are updated.
* @param status new status
* @throws Exception an exception
*/
public void updateArchiveStatus(String lidvid, String status) throws Exception

Check failure on line 47 in common/src/main/java/gov/nasa/pds/registry/common/es/service/ProductService.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 21 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=NASA-PDS_registry-loader&issues=AZ00u21dPU4l3pg_5nKk&open=AZ00u21dPU4l3pg_5nKk&pullRequest=57
{
log.info("Setting product status and its references if bundle or collection. LIDVID = " + lidvid + ", status = " + status);
int total = 1;

String resolvedLidvid = lidvid;
String pClass = dao.getProductClass(lidvid);
if(pClass == null)
if(pClass == null)
{
log.warn("Unknown LIDVID: " + lidvid);
return;
// If the input has no version component it may be a bare LID; try to resolve it.
if(!lidvid.contains("::"))
{
List<String> resolved = dao.getLatestLidVids(Collections.singletonList(lidvid));
if(resolved != null && !resolved.isEmpty())
{
resolvedLidvid = resolved.get(0);
log.info("Resolved bare LID " + lidvid + " to LIDVID " + resolvedLidvid);

Check warning on line 63 in common/src/main/java/gov/nasa/pds/registry/common/es/service/ProductService.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the built-in formatting to construct this argument.

See more on https://sonarcloud.io/project/issues?id=NASA-PDS_registry-loader&issues=AZ00u21dPU4l3pg_5nKh&open=AZ00u21dPU4l3pg_5nKh&pullRequest=57

Check warning on line 63 in common/src/main/java/gov/nasa/pds/registry/common/es/service/ProductService.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Format specifiers should be used instead of string concatenation.

See more on https://sonarcloud.io/project/issues?id=NASA-PDS_registry-loader&issues=AZ00u21dPU4l3pg_5nKl&open=AZ00u21dPU4l3pg_5nKl&pullRequest=57
pClass = dao.getProductClass(resolvedLidvid);
}
}

if(pClass == null)
{
throw new Exception("Unknown LID/LIDVID: " + lidvid

Check warning on line 70 in common/src/main/java/gov/nasa/pds/registry/common/es/service/ProductService.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace generic exceptions with specific library exceptions or a custom exception.

See more on https://sonarcloud.io/project/issues?id=NASA-PDS_registry-loader&issues=AZ00u21dPU4l3pg_5nKj&open=AZ00u21dPU4l3pg_5nKj&pullRequest=57
+ ". Verify that the identifier exists in the registry and that a full"
+ " LIDVID (e.g. urn:nasa:pds:bundle::1.0) is provided when multiple"
+ " versions are present.");
}
}

// Update the product
dao.updateArchiveStatus(Arrays.asList(lidvid), status);
dao.updateArchiveStatus(Arrays.asList(resolvedLidvid), status);

// Update collection inventory
if("Product_Collection".equals(pClass))
{
log.info("Setting status of primary references from collection inventory");
total += updateCollectionInventory(lidvid, status);
total += updateCollectionInventory(resolvedLidvid, status);
}
else if("Product_Bundle".equals(pClass))
{
// Get collection IDs. There could be both LIDs and LIDVIDs at the same time.
LidvidSet collectionIds = dao.getCollectionIds(lidvid);
if(collectionIds == null) return;

Set<String> lidvids = new TreeSet<String>();
if(collectionIds.lidvids != null) lidvids.addAll(collectionIds.lidvids);

List<String> tmp = dao.getLatestLidVids(collectionIds.lids);
if(tmp != null) lidvids.addAll(tmp);
LidvidSet collectionIds = dao.getCollectionIds(resolvedLidvid);

Set<String> lidvids = new TreeSet<String>();
if(collectionIds != null)
{
if(collectionIds.lidvids != null) lidvids.addAll(collectionIds.lidvids);

List<String> tmp = dao.getLatestLidVids(collectionIds.lids);
if(tmp != null) lidvids.addAll(tmp);
}

if(lidvids.isEmpty())
{
log.warn("No collection references found for bundle " + resolvedLidvid
+ ". Verify that the bundle document contains 'ref_lid_collection' or"
+ " 'ref_lidvid_collection' fields.");

Check warning on line 104 in common/src/main/java/gov/nasa/pds/registry/common/es/service/ProductService.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use the built-in formatting to construct this argument.

See more on https://sonarcloud.io/project/issues?id=NASA-PDS_registry-loader&issues=AZ00u21dPU4l3pg_5nKi&open=AZ00u21dPU4l3pg_5nKi&pullRequest=57

Check warning on line 104 in common/src/main/java/gov/nasa/pds/registry/common/es/service/ProductService.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Format specifiers should be used instead of string concatenation.

See more on https://sonarcloud.io/project/issues?id=NASA-PDS_registry-loader&issues=AZ00u21dPU4l3pg_5nKm&open=AZ00u21dPU4l3pg_5nKm&pullRequest=57
}

total += updateCollections(lidvids, status);
}
Expand Down
Loading
Loading