ContainerRuleRegistry.java
/*******************************************************************************
* Copyright (c) 2026 Carsten Hammer.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.sandbox.jdt.container.analysis;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.sandbox.jdt.container.api.ContainerRuleDescriptor;
import org.sandbox.jdt.container.api.ContainerRuleDescriptor.RuleOwnership;
import org.sandbox.jdt.container.api.ContainerShape;
/**
* Central inventory used to prevent semantic container analysis from duplicating
* existing local cleanups and refactorings.
*/
public final class ContainerRuleRegistry {
public static final String ARRAY_APPEND_SEQUENCE= "semantic.array.append.sequence"; //$NON-NLS-1$
public static final String UNIQUE_SEQUENCE_SET= "semantic.sequence.unique.set"; //$NON-NLS-1$
public static final String COLLECTION_BULK_ADD= "existing.collection.bulk-add"; //$NON-NLS-1$
public static final String COLLECTION_COPY_CONSTRUCTOR= "existing.collection.copy-constructor"; //$NON-NLS-1$
public static final String ARRAY_FILL= "existing.array.fill"; //$NON-NLS-1$
public static final String TYPE_GENERALIZATION= "existing.type.generalization"; //$NON-NLS-1$
private static final Map<String, ContainerRuleDescriptor> RULES= createRules();
private ContainerRuleRegistry() {
// Static registry.
}
/** Returns one descriptor by stable identifier. */
public static Optional<ContainerRuleDescriptor> find(String ruleId) {
return Optional.ofNullable(RULES.get(ruleId));
}
/** Returns descriptors in deterministic registration order. */
public static List<ContainerRuleDescriptor> all() {
return List.copyOf(RULES.values());
}
/** Returns the descriptor for append-array to sequence migration. */
public static ContainerRuleDescriptor arrayAppendSequence() {
return RULES.get(ARRAY_APPEND_SEQUENCE);
}
/** Returns the descriptor for manually unique sequence to ordered-set migration. */
public static ContainerRuleDescriptor uniqueSequenceSet() {
return RULES.get(UNIQUE_SEQUENCE_SET);
}
private static Map<String, ContainerRuleDescriptor> createRules() {
Map<String, ContainerRuleDescriptor> rules= new LinkedHashMap<>();
register(rules, new ContainerRuleDescriptor(
COLLECTION_BULK_ADD,
ContainerShape.LIST,
ContainerShape.LIST,
RuleOwnership.DUPLICATE,
"Eclipse collection bulk-add cleanup", //$NON-NLS-1$
"Local loop-to-bulk-add syntax is already owned by an existing cleanup.")); //$NON-NLS-1$
register(rules, new ContainerRuleDescriptor(
COLLECTION_COPY_CONSTRUCTOR,
ContainerShape.LIST,
ContainerShape.LIST,
RuleOwnership.DUPLICATE,
"Eclipse collection copy-constructor cleanup", //$NON-NLS-1$
"Local construction followed by copying is already normalized elsewhere.")); //$NON-NLS-1$
register(rules, new ContainerRuleDescriptor(
ARRAY_FILL,
ContainerShape.ARRAY,
ContainerShape.ARRAY,
RuleOwnership.DUPLICATE,
"Eclipse array-fill cleanup", //$NON-NLS-1$
"Replacing a uniform assignment loop with array fill is a local syntax cleanup.")); //$NON-NLS-1$
register(rules, new ContainerRuleDescriptor(
TYPE_GENERALIZATION,
ContainerShape.LIST,
ContainerShape.LIST,
RuleOwnership.DUPLICATE,
"Eclipse Change Type and Sandbox Use General Type", //$NON-NLS-1$
"Changing only the declared supertype is already covered by type-generalization tools.")); //$NON-NLS-1$
register(rules, new ContainerRuleDescriptor(
UNIQUE_SEQUENCE_SET,
ContainerShape.LIST,
ContainerShape.SET,
RuleOwnership.NOVEL,
"", //$NON-NLS-1$
"The rule changes duplicate semantics in the declared contract " //$NON-NLS-1$
+ "and may require coordinated signature migration.")); //$NON-NLS-1$
register(rules, new ContainerRuleDescriptor(
ARRAY_APPEND_SEQUENCE,
ContainerShape.ARRAY,
ContainerShape.LIST,
RuleOwnership.NOVEL,
"", //$NON-NLS-1$
"The rule changes representation and may propagate through fields, signatures and callers.")); //$NON-NLS-1$
return Collections.unmodifiableMap(new LinkedHashMap<>(rules));
}
private static void register(
Map<String, ContainerRuleDescriptor> rules,
ContainerRuleDescriptor descriptor) {
if (rules.putIfAbsent(descriptor.ruleId(), descriptor) != null) {
throw new IllegalStateException("Duplicate container rule id: " + descriptor.ruleId()); //$NON-NLS-1$
}
}
}