Abstract Collectables & Dynamic Registries
Extending abstract base classes and the Comparable interface to build dynamic registries, multi-field ordering, and data-driven student survey profiles.
CS112 Core Object-Oriented & Collection Standards
| Course Standard | Core Concept / Skill | Implementation Artifact in OCS Architecture |
|---|---|---|
| CS112-OOP-1 | Interfaces & Polymorphism | Collectable interface defining contracts (getMap, getKeys, getValue, compareTo) implemented by Animal, Student, and attribute components. |
| CS112-OOP-2 | Generic Types & Bounded Containers | Catalog<T extends Collectable> enforcing type safety while preserving reusable storage behavior across different data types. |
| CS112-DS-1 | Linear Data Structures & Custom Maps | Registry utilizing ArrayList, LinkedHashMap, and Map.computeIfAbsent for dynamic grouping and categorization. |
| CS112-ALG-1 | Sorting & Ordering Algorithms | Natural sorting via Comparable.compareTo and alternate dynamic field-based sorting via Java Comparator lambdas. |
CS113 Advanced Data Structures & Analysis Standards
| Course Standard | Core Concept / Skill | Implementation Artifact in OCS Architecture |
|---|---|---|
| CS113-DS-2 | Projected Views & Decorator Pattern | ProjectedCollectable wrapper record restructuring map projections to surface primary search/sort keys as the lead column. |
| CS113-ALG-2 | Algorithm Efficiency & Indexing | Dynamic field lookup evaluation (getValue(key)) across heterogeneous item collections to support flexible sorting and searching without redundant structures. |
| CS113-TEST-1 | Boundary & Invariant Verification | Handling edge cases across sorting inputs (empty catalogs, singletons, duplicate matches, and missing attribute keys). |
| CS113-PBL-1 | Project Integration & Architecture | Mapping domain entities (student records, pathways, standings) directly to data stores, making application state inspectable and web-ready. |
Abstract Collectables
Data Projection & Transformation Flow
Before looking at the class structure, it helps to see how individual data records are converted into maps, sorted, and dynamically reordered using the decorator pattern.
graph TD
subgraph Raw Data Object
A[Student Entity] -->|"getMap()"| B["{Name=Bill Gates, Standing=Freshman, Pathway Year=0}"]
end
subgraph "Projected View (Decorator Pattern)"
B -->|"orderBy('Pathway Year')"| C["{Pathway Year=0, Name=Bill Gates, Standing=Freshman}"]
end
Architectural Class Hierarchy
Once you understand how the data flows, here is the object-oriented design showing how interfaces, abstract base classes, catalogs, and registries fit together.
classDiagram
direction TD
class Collectable {
<<interface>>
+getMap() Map
+getKeys() List
+getValue(key) Object
+compareTo(o) int
}
class AbstractCollectable {
<<abstract>>
+getKeys() List
+getValue(key) Object
+toString() String
}
class Animal {
-String name
-String species
-int age
+getMap() Map
+compareTo(o) int
}
class Student {
-String name
-Standing standing
-Pathway pathway
-String archetype
+getMap() Map
+compareTo(o) int
}
class Pathway {
-int year
-String projectCapability
+getMap() Map
}
class Standing {
-String label
-int weight
+getMap() Map
}
class ProjectedCollectable {
-Collectable delegate
-String primaryKey
+getMap() Map
}
class Catalog {
-List~T~ items
+add(T item)
+getItems() List
+display()
}
class Registry {
-List~Collectable~ items
+sortNatural() List
+sortByField(key) List
+orderBy(key) List
+groupBy(key) Map
}
%% Is-A Relationships (Inheritance & Implementation)
Collectable <|.. AbstractCollectable : implements
AbstractCollectable <|-- Animal : extends
AbstractCollectable <|-- Student : extends
AbstractCollectable <|-- Pathway : extends
AbstractCollectable <|-- Standing : extends
Collectable <|.. ProjectedCollectable : implements
%% Has-A Relationships (Composition & Association)
Catalog o-- Collectable : stores T
Registry --> Catalog : analyzes
Student --> Standing : has-a
Student --> Pathway : has-a
ProjectedCollectable --> Collectable : delegates to
Hacks
To become familiar with Abstract collectables, it works best with a task.
Extend the existing OCS Student profile architecture by turning the survey’s Fantasy Persona and Achievement Orientation options into data-driven classes extending AbstractCollectable. Or define your own task starting with the Animals example.
But, please feel free to adapt this task to something related to your own project or interests.
Part 0: Plan to enhance the Student definitions
Make a class FantasyStudent and class FantasyStudents. Be sure to retain original Student outputs and thus be able to show your enhanced FantasyStudent outputs. This is part of your classroom success, using the submission tooling and coming up with best use case strategies.
- Build an assignment to enable submission and create it to use AI autograding.
- Be sure to update Hack header to reflect your purpose and perform a Link submission.
- If you adapt a Collectables lesson with CodeRunners and submit as Code that would be worth above and beyond consideration.
- Be informed, once again, that you can vary from FantasyStudent to another topic, I would like to encourages choice and purpose in assignments.
Part 1: Create a Data-Driven Attribute Class
The remainder of this hack outlines the Fantasy Persona.
Create a new class named FantasyPersona (or choose another survey category like SocialInterest). This data can be found in your OCS Profile.
-
Extend AbstractCollectable.
-
Give it private fields appropriate for the persona (e.g., String name, String superpower).
-
Implement the required getMap() method to project its attributes and compareTo() for natural ordering.
Part 2: Part 2: Integrate into the FantasyStudent Entity
-
Update your FantasyStudent class composition so that it holds a reference to your new FantasyPersona object (replacing or augmenting existing fields).
-
Update FantasyStudent.getMap() so that the new persona’s attributes are correctly exposed for dynamic lookup.
Part 3: Registry & Testing Execution
-
Build a master catalog of available FantasyPersona records (e.g., Speedster, Powerhouse, Mastermind, Visionary).
-
Instantiate at least 4 distinct Student records assigned to different personas, standings, and pathways.
Wrap your FantasyStudent catalog in a Registry and write code for enhanced demonstrations:
-
Natural Sorting of students.
-
Alternate Sorting / Ordering (orderBy) by pathway year or student standing.
-
Categorized Grouping (groupBy) to partition your classroom roster by FantasyPersona.
Collectable
Represents a single record or row within a collection. Provides a standardized way to access data via keys and supports natural ordering through the Comparable interface.
import java.util.Map;
import java.util.List;
/**
* Collectable Interface
*
* Defines a standardized data-access and comparison contract for multiple domain entities.
*
* Key Instructional Concepts:
* - Polymorphism: Allows different data classes to be treated uniformly through this interface.
* - Natural Ordering: Extends Comparable to enforce a default sorting mechanism.
* - Map Projection: Exposes object fields as key-value pairs for dynamic inspection.
*
* @author John Mortensen
* @version 2.0
*/
public interface Collectable extends Comparable<Collectable> {
/**
* Requires the object's internal fields to be projected into a key-value map representation.
*
* @return A Map containing field names as keys and their respective values.
*/
Map<String, Object> getMap();
/**
* Retrieves all available field keys for this collectable entity.
*
* @return A List of String keys representing the entity's attributes.
*/
List<String> getKeys();
/**
* Fetches the value of a specific field dynamically by its key string.
*
* @param key The attribute key to look up.
* @return The Object value associated with the given key.
*/
Object getValue(String key);
}
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* AbstractCollectable Base Class
*
* Provides shared default implementations for common Collectable behaviors
* (like toString, getKeys, and getValue) derived entirely from getMap().
*
* Key Instructional Concepts:
* - Abstract Classes vs Interfaces: Using abstract classes to share code implementation while
* enforcing contract implementation via interfaces.
* - Template Method Pattern: Subclasses only need to supply getMap() and compareTo().
*/
public abstract class AbstractCollectable implements Collectable {
@Override
public List<String> getKeys() {
return new ArrayList<>(getMap().keySet());
}
@Override
public Object getValue(String key) {
return getMap().get(key);
}
@Override
public String toString() {
return getMap().toString();
}
}
Catalog
Acts as the data repository for the collection, functioning similarly to a database table.
import java.util.*;
/**
* Catalog Class
*
* Serves as a generic container for managing a collection of Collectable items.
*
* Key Instructional Concepts:
* - Generics: Uses <T extends Collectable> to ensure type safety while allowing flexibility.
* - Encapsulation: Manages an internal list of items, providing controlled access via methods.
* - Collection Management: Demonstrates basic CRUD-like operations (add, retrieve, display).
*
* @author John Mortensen
* @version 2.0
*/
public class Catalog<T extends Collectable> {
private List<T> items = new ArrayList<>();
/**
* Adds a new item to the catalog.
*
* @param item The Collectable item to be added.
*/
public void add(T item) { items.add(item); }
/**
* Retrieves the full list of items currently in the catalog.
*
* @return A List containing all stored items.
*/
public List<T> getItems() { return items; }
/**
* Iterates through the items and prints them to the standard output.
*/
public void display() {
for (T item : items) {
System.out.println(item);
}
}
}
Registry
Provides polymorphic sorting and grouping across any Collectable collection.
import java.util.*;
/**
* Registry Class
*
* Provides advanced processing, sorting, and classification services across mixed or
* uniform Collectable catalogs.
*
* Key Instructional Concepts:
* - Wildcard Generics with Upper Bounds (? extends Collectable): Allows the Registry to accept
* catalogs of any subtype (e.g., Catalog<Student> or Catalog<Animal>).
* - Dynamic Field Sorting: Uses Java Comparators to sort items on-the-fly based on string-keyed
* attributes rather than fixed properties.
* - Categorized Grouping: Uses hash-based map aggregation (Map.computeIfAbsent) to partition
* items into sub-lists by attribute.
*
* @author John Mortensen
* @version 2.0
*/
public class Registry {
private List<Collectable> items;
public Registry(Catalog<? extends Collectable> catalog) {
this.items = new ArrayList<>(catalog.getItems());
}
/**
* A decorator that reorders the map projection so the primaryKey appears first.
*/
public record ProjectedCollectable(Collectable delegate, String primaryKey) implements Collectable {
@Override
public Map<String, Object> getMap() {
Map<String, Object> original = delegate.getMap();
Map<String, Object> reordered = new LinkedHashMap<>();
if (original.containsKey(primaryKey)) {
reordered.put(primaryKey, original.get(primaryKey));
}
original.forEach((k, v) -> {
if (!k.equals(primaryKey)) reordered.put(k, v);
});
return reordered;
}
@Override public List<String> getKeys() { return getMap().keySet().stream().toList(); }
@Override public Object getValue(String key) { return getMap().get(key); }
@Override public int compareTo(Collectable o) { return delegate.compareTo(o); }
/**
* Overriding the record's default toString to use the reordered map.
*/
@Override
public String toString() {
return getMap().toString();
}
}
// Objective: Natural Sorting (using compareTo)
public List<Collectable> sortNatural() {
List<Collectable> sorted = new ArrayList<>(items);
Collections.sort(sorted);
return sorted;
}
// Objective: Alternate Sorting (dynamic field sorting)
public List<Collectable> sortByField(String key) {
List<Collectable> sorted = new ArrayList<>(items);
sorted.sort((a, b) -> {
Object valA = a.getValue(key);
Object valB = b.getValue(key);
if (valA instanceof Comparable && valB instanceof Comparable) {
return ((Comparable) valA).compareTo(valB);
}
return 0;
});
return sorted;
}
/**
* Sorts the collection by the specified key and returns a projected view
* where the sort key is moved to the first column.
*/
public List<ProjectedCollectable> orderBy(String key) {
return sortByField(key).stream()
.map(item -> new ProjectedCollectable(item, key))
.toList();
}
// Objective: Grouping by attribute key
public Map<Object, List<Collectable>> groupBy(String key) {
Map<Object, List<Collectable>> groupedMap = new LinkedHashMap<>();
for (Collectable item : items) {
Object groupKey = item.getValue(key);
groupedMap.computeIfAbsent(groupKey, k -> new ArrayList<>()).add(item);
}
return groupedMap;
}
}
Educational Use Case
import java.util.*;
/**
* Pathway Class
*
* Represents a specific curriculum track or learning journey.
*
* Key Instructional Concepts:
* - Domain Modeling: Translates real-world curriculum attributes into a structured object.
* - Data Projection: Implements `getMap()` to allow dynamic access to its fields.
* - Natural Ordering: Implements `Comparable` to sort pathways by year.
*
* @author John Mortensen
* @version 2.0
*/
public class Pathway extends AbstractCollectable {
private int year;
private String projectCapability;
private String scrumTeamCapability;
private String problemSolving;
private String initiative;
public Pathway(int year, String projectCapability, String scrumTeamCapability, String problemSolving, String initiative) {
this.year = year;
this.projectCapability = projectCapability;
this.scrumTeamCapability = scrumTeamCapability;
this.problemSolving = problemSolving;
this.initiative = initiative;
}
public int getYear() { return year; }
public String getProjectCapability() { return projectCapability; }
@Override
public Map<String, Object> getMap() {
Map<String, Object> map = new LinkedHashMap<>();
map.put("Year", year);
map.put("Project Capability", projectCapability);
map.put("Scrum Team", scrumTeamCapability);
map.put("Problem Solving", problemSolving);
map.put("Initiative", initiative);
return map;
}
@Override public int compareTo(Collectable o) { return Integer.compare(this.year, (Integer) o.getValue("Year")); }
/**
* Returns a pre-populated catalog of curriculum pathways.
*
* @return A Catalog containing the four standard pathway years (0-3).
*/
public static Catalog<Pathway> catalog() {
Catalog<Pathway> catalog = new Catalog<>();
catalog.add(new Pathway(0, "Fundamental", "Solo", "Remembering", "Passive"));
catalog.add(new Pathway(1, "Project", "Pair (2-3)", "Analyzing", "Self-starter"));
catalog.add(new Pathway(2, "System", "Group (~6)", "Applying", "Shaper"));
catalog.add(new Pathway(3, "Research", "Team (~10)", "Creating", "Driver"));
return catalog;
}
}
import java.util.*;
/**
* Standing Class
*
* Represents an academic or professional status level.
*
* Key Instructional Concepts:
* - Attribute Weighting: Uses a numeric weight to facilitate mathematical comparisons.
* - Data Projection: Implements `getMap()` for dynamic attribute inspection.
* - Natural Ordering: Implements `Comparable` to sort by weight.
*
* @author John Mortensen
* @version 2.0
*/
public class Standing extends AbstractCollectable {
private String label;
private int weight;
public Standing(String label, int weight) {
this.label = label;
this.weight = weight;
}
public String getLabel() { return label; }
public int getWeight() { return weight; }
@Override
public Map<String, Object> getMap() {
Map<String, Object> map = new LinkedHashMap<>();
map.put("Label", label);
map.put("Weight", weight);
return map;
}
@Override public int compareTo(Collectable o) { return Integer.compare(this.weight, (Integer) o.getValue("Weight")); }
/**
* Returns a pre-populated catalog of academic standings.
*
* @return A Catalog containing Freshman, Sophomore, Junior, and Senior standings.
*/
public static Catalog<Standing> catalog() {
Catalog<Standing> catalog = new Catalog<>();
catalog.add(new Standing("Freshman", 0));
catalog.add(new Standing("Sophomore", 1));
catalog.add(new Standing("Junior", 2));
catalog.add(new Standing("Senior", 3));
return catalog;
}
}
import java.util.*;
/**
* Student Class
*
* A complex domain entity that aggregates multiple `Collectable` components.
*
* Key Instructional Concepts:
* - Composition: Demonstrates how a class can be composed of other complex objects (`Standing`, `Pathway`).
* - Dependency Management: Shows how a parent entity relies on the state of its child components.
* - Polymorphic Comparison: Implements `compareTo` to provide a natural sort order based on the student's name.
* - Map Projection: Flattens hierarchical data into a single-level map for easy registry access.
*
* @author John Mortensen
* @version 2.0
*/
public class Student extends AbstractCollectable {
private String name;
private Standing standing;
private Pathway pathway;
private String archetype;
public Student(String name, Standing standing, Pathway pathway, String archetype) {
this.name = name;
this.standing = standing;
this.pathway = pathway;
this.archetype = archetype;
}
public String getName() { return name; }
public Standing getStanding() { return standing; }
public Pathway getPathway() { return pathway; }
public String getArchetype() { return archetype; }
@Override
public Map<String, Object> getMap() {
Map<String, Object> map = new LinkedHashMap<>();
map.put("Name", name);
map.put("Standing", standing.getLabel());
map.put("Standing Weight", standing.getWeight());
map.put("Pathway Year", pathway.getYear());
map.put("Technical Capability", pathway.getProjectCapability());
map.put("Archetype", archetype);
return map;
}
@Override
public int compareTo(Collectable o) {
// Natural sorting by Name alphabetically
return this.name.compareTo((String) o.getValue("Name"));
}
}
import java.util.*;
/**
* Students Driver Class
*
* Serves as the main entry point for the demonstration, orchestrating the interaction
* between Catalogs, Registries, and domain entities.
*
* Key Instructional Concepts:
* - System Orchestration: Demonstrates how to initialize reference data and primary rosters.
* - Registry Usage: Shows how a `Registry` can be used to perform complex operations on a `Catalog`.
* - Data-Driven Testing: Uses a series of print statements to verify sorting, grouping, and display logic.
*
* @author John Mortensen
* @version 2.0
*/
public class Students {
public static Catalog<Student> catalog() {
// Master Catalog for Reference Data (Pathways & Standings)
Catalog<Pathway> pathwayCatalog = Pathway.catalog();
Catalog<Standing> standingCatalog = Standing.catalog();
// Student Roster Catalog
Catalog<Student> studentCatalog = new Catalog<>();
studentCatalog.add(new Student("Thomas Edison", standingCatalog.getItems().get(3), pathwayCatalog.getItems().get(3), "Scrummer"));
studentCatalog.add(new Student("Nikola Tesla", standingCatalog.getItems().get(3), pathwayCatalog.getItems().get(2), "Technologist"));
studentCatalog.add(new Student("Grace Hopper", standingCatalog.getItems().get(2), pathwayCatalog.getItems().get(3), "Planner"));
studentCatalog.add(new Student("Marie Curie", standingCatalog.getItems().get(2), pathwayCatalog.getItems().get(1), "Analyst"));
studentCatalog.add(new Student("Alan Turing", standingCatalog.getItems().get(2), pathwayCatalog.getItems().get(1), "Technologist"));
studentCatalog.add(new Student("Hedy Lamarr", standingCatalog.getItems().get(2), pathwayCatalog.getItems().get(2), "Planner"));
studentCatalog.add(new Student("isaac Newton", standingCatalog.getItems().get(1), pathwayCatalog.getItems().get(0), "Analyst"));
studentCatalog.add(new Student("Bill Gates", standingCatalog.getItems().get(0), pathwayCatalog.getItems().get(0), "Analyst"));
return studentCatalog;
}
public static void main(String[] args) {
// Initialize the student catalog
Catalog<Student> studentCatalog = catalog();
// Initialize the registry with the student catalog
Registry registry = new Registry(studentCatalog);
// View the student catalog
System.out.println("=== 1. Student toString() & Catalog Display ===");
studentCatalog.display();
// Sort and View the registry naturally (by Name)
System.out.println("\n=== 2. Natural Sorting (compareTo by Name) ===");
registry.sortNatural().forEach(System.out::println);
// Sort and View the registry by an alternate field (Pathway Year)
System.out.println("\n=== 3. Alternate Sorting (by Pathway Year) ===");
registry.orderBy("Pathway Year").forEach(System.out::println);
// Group the registry by Archetype using groupBy functionality
System.out.println("\n=== 4. Grouping by Archetype ===");
Map<Object, List<Collectable>> grouped = registry.groupBy("Archetype");
grouped.forEach((key, value) -> {
System.out.println("Archetype: " + key);
value.forEach(item -> System.out.println(" - " + item));
});
}
}
Students.main(null);
=== 1. Student toString() & Catalog Display ===
{Name=Thomas Edison, Standing=Senior, Standing Weight=3, Pathway Year=3, Technical Capability=Research, Archetype=Scrummer}
{Name=Nikola Tesla, Standing=Senior, Standing Weight=3, Pathway Year=2, Technical Capability=System, Archetype=Technologist}
{Name=Grace Hopper, Standing=Junior, Standing Weight=2, Pathway Year=3, Technical Capability=Research, Archetype=Planner}
{Name=Marie Curie, Standing=Junior, Standing Weight=2, Pathway Year=1, Technical Capability=Project, Archetype=Analyst}
{Name=Alan Turing, Standing=Junior, Standing Weight=2, Pathway Year=1, Technical Capability=Project, Archetype=Technologist}
{Name=Hedy Lamarr, Standing=Junior, Standing Weight=2, Pathway Year=2, Technical Capability=System, Archetype=Planner}
{Name=isaac Newton, Standing=Sophomore, Standing Weight=1, Pathway Year=0, Technical Capability=Fundamental, Archetype=Analyst}
{Name=Bill Gates, Standing=Freshman, Standing Weight=0, Pathway Year=0, Technical Capability=Fundamental, Archetype=Analyst}
=== 2. Natural Sorting (compareTo by Name) ===
{Name=Alan Turing, Standing=Junior, Standing Weight=2, Pathway Year=1, Technical Capability=Project, Archetype=Technologist}
{Name=Bill Gates, Standing=Freshman, Standing Weight=0, Pathway Year=0, Technical Capability=Fundamental, Archetype=Analyst}
{Name=Grace Hopper, Standing=Junior, Standing Weight=2, Pathway Year=3, Technical Capability=Research, Archetype=Planner}
{Name=Hedy Lamarr, Standing=Junior, Standing Weight=2, Pathway Year=2, Technical Capability=System, Archetype=Planner}
{Name=Marie Curie, Standing=Junior, Standing Weight=2, Pathway Year=1, Technical Capability=Project, Archetype=Analyst}
{Name=Nikola Tesla, Standing=Senior, Standing Weight=3, Pathway Year=2, Technical Capability=System, Archetype=Technologist}
{Name=Thomas Edison, Standing=Senior, Standing Weight=3, Pathway Year=3, Technical Capability=Research, Archetype=Scrummer}
{Name=isaac Newton, Standing=Sophomore, Standing Weight=1, Pathway Year=0, Technical Capability=Fundamental, Archetype=Analyst}
=== 3. Alternate Sorting (by Pathway Year) ===
{Pathway Year=0, Name=isaac Newton, Standing=Sophomore, Standing Weight=1, Technical Capability=Fundamental, Archetype=Analyst}
{Pathway Year=0, Name=Bill Gates, Standing=Freshman, Standing Weight=0, Technical Capability=Fundamental, Archetype=Analyst}
{Pathway Year=1, Name=Marie Curie, Standing=Junior, Standing Weight=2, Technical Capability=Project, Archetype=Analyst}
{Pathway Year=1, Name=Alan Turing, Standing=Junior, Standing Weight=2, Technical Capability=Project, Archetype=Technologist}
{Pathway Year=2, Name=Nikola Tesla, Standing=Senior, Standing Weight=3, Technical Capability=System, Archetype=Technologist}
{Pathway Year=2, Name=Hedy Lamarr, Standing=Junior, Standing Weight=2, Technical Capability=System, Archetype=Planner}
{Pathway Year=3, Name=Thomas Edison, Standing=Senior, Standing Weight=3, Technical Capability=Research, Archetype=Scrummer}
{Pathway Year=3, Name=Grace Hopper, Standing=Junior, Standing Weight=2, Technical Capability=Research, Archetype=Planner}
=== 4. Grouping by Archetype ===
Archetype: Scrummer
- {Name=Thomas Edison, Standing=Senior, Standing Weight=3, Pathway Year=3, Technical Capability=Research, Archetype=Scrummer}
Archetype: Technologist
- {Name=Nikola Tesla, Standing=Senior, Standing Weight=3, Pathway Year=2, Technical Capability=System, Archetype=Technologist}
- {Name=Alan Turing, Standing=Junior, Standing Weight=2, Pathway Year=1, Technical Capability=Project, Archetype=Technologist}
Archetype: Planner
- {Name=Grace Hopper, Standing=Junior, Standing Weight=2, Pathway Year=3, Technical Capability=Research, Archetype=Planner}
- {Name=Hedy Lamarr, Standing=Junior, Standing Weight=2, Pathway Year=2, Technical Capability=System, Archetype=Planner}
Archetype: Analyst
- {Name=Marie Curie, Standing=Junior, Standing Weight=2, Pathway Year=1, Technical Capability=Project, Archetype=Analyst}
- {Name=isaac Newton, Standing=Sophomore, Standing Weight=1, Pathway Year=0, Technical Capability=Fundamental, Archetype=Analyst}
- {Name=Bill Gates, Standing=Freshman, Standing Weight=0, Pathway Year=0, Technical Capability=Fundamental, Archetype=Analyst}
Animal References
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Animal Class
*
* Represents a concrete domain entity implementing the Collectable contract.
* This class models simple animal records with a name, species, and age.
*
* Key Instructional Concepts:
* - Interface Implementation: Fulfills the Collectable contract for uniform processing.
* - Natural Ordering: Implements compareTo() to define default sorting behavior (alphabetical by name).
* - Data Projection: Implements getMap() to expose object attributes dynamically for registry mapping.
*
* @author John Mortensen
* @version 2.0
*/
public class Animal extends AbstractCollectable {
private String name;
private String species;
private int age;
/**
* Constructs a new Animal record.
*
* @param name The name of the animal.
* @param species The biological species or category.
* @param age The age of the animal in years.
*/
public Animal(String name, String species, int age) {
this.name = name;
this.species = species;
this.age = age;
}
public String getName() { return name; }
public String getSpecies() { return species; }
public int getAge() { return age; }
/**
* Projects internal fields into a LinkedHashMap to maintain insertion order
* when inspected dynamically by registries or export tools.
*/
@Override
public Map<String, Object> getMap() {
Map<String, Object> map = new LinkedHashMap<>();
map.put("Name", name);
map.put("Species", species);
map.put("Age", age);
return map;
}
/**
* Defines natural ordering (Comparable interface contract).
* Compares animals alphabetically by their name field.
*/
@Override
public int compareTo(Collectable o) {
// Safe extraction and comparison of the "Name" attribute from another Collectable entity
String otherName = (String) o.getValue("Name");
return this.name.compareTo(otherName);
}
}
/**
* Animals Tester Class
*
* Serves as an executable runner to demonstrate catalog management, natural sorting,
* alternate dynamic field sorting, and grouping using the shared Registry architecture.
*
* Key Instructional Concepts:
* - Polymorphism in Action: Demonstrates how a shared Registry handles Animal entities
* through the Collectable interface abstraction.
* - Separation of Concerns: Catalog handles data storage, Registry handles processing and organization.
*
* @author John Mortensen
* @version 2.0
*/
public class Animals {
public static void main(String[] args) {
// 1. Initialize a generic Catalog bounded to Animal entities
Catalog<Animal> animalCatalog = new Catalog<>();
// Populate the catalog with sample records (out of alphabetical order to test sorting)
animalCatalog.add(new Animal("Zebra", "Mammal", 5));
animalCatalog.add(new Animal("Aardvark", "Mammal", 3));
animalCatalog.add(new Animal("Falcon", "Bird", 2));
animalCatalog.add(new Animal("Baboon", "Mammal", 4));
// 2. Wrap the catalog inside the Registry processor
Registry registry = new Registry(animalCatalog);
// 3. Demonstrate standard display utilizing polymorphic toString()
System.out.println("=== 1. Catalog Display (Insertion Order) ===");
animalCatalog.display();
// 4. Demonstrate natural sorting via compareTo() (Alphabetical by Name)
System.out.println("\n=== 2. Natural Sorting (Alphabetical by Name) ===");
registry.sortNatural().forEach(System.out::println);
// 5. Demonstrate alternate dynamic sorting by a non-default field key ("Age")
System.out.println("\n=== 3. Alternate Sorting (Dynamic Sort by Age) ===");
registry.orderBy("Age").forEach(System.out::println);
// 6. Demonstrate data grouping/partitioning by an attribute key ("Species")
System.out.println("\n=== 4. Categorized Grouping by Species ===");
registry.groupBy("Species").forEach((species, list) -> {
System.out.println("Species Group: " + species);
list.forEach(animal -> System.out.println(" - " + animal));
});
}
}
Animals.main(null);
=== 1. Catalog Display (Insertion Order) ===
{Name=Zebra, Species=Mammal, Age=5}
{Name=Aardvark, Species=Mammal, Age=3}
{Name=Falcon, Species=Bird, Age=2}
{Name=Baboon, Species=Mammal, Age=4}
=== 2. Natural Sorting (Alphabetical by Name) ===
{Name=Aardvark, Species=Mammal, Age=3}
{Name=Baboon, Species=Mammal, Age=4}
{Name=Falcon, Species=Bird, Age=2}
{Name=Zebra, Species=Mammal, Age=5}
=== 3. Alternate Sorting (Dynamic Sort by Age) ===
{Age=2, Name=Falcon, Species=Bird}
{Age=3, Name=Aardvark, Species=Mammal}
{Age=4, Name=Baboon, Species=Mammal}
{Age=5, Name=Zebra, Species=Mammal}
=== 4. Categorized Grouping by Species ===
Species Group: Mammal
- {Name=Zebra, Species=Mammal, Age=5}
- {Name=Aardvark, Species=Mammal, Age=3}
- {Name=Baboon, Species=Mammal, Age=4}
Species Group: Bird
- {Name=Falcon, Species=Bird, Age=2}
LxD - Abstract Collectables & Dynamic Registries
Empathize: Students need to model a data set. This process begins in Java and extends to Spring, particularly with the transfer of data from POJO → JPA → API. Data needs to be organized and transferred. Java abstractions of classes and relationships are fundamental to systems and to students’ data structure education.
Define:
- POV: CSA students need to learn data structures and understand Java interfaces, abstract classes, and inheritance (extends). Additionally, they need to build Abstract Data Types to optimize code reuse, data safety, and information retrieval.
- Learning Goal: Teach students how to store, manage, and present a collection. Data sorting, grouping, and ordering are key data presentation techniques.
Ideate:
- HMW Question: How can we manage cognitive load, teach Java data structures, and use OCS examples?
- HMW Question: How can we learn with meaningful examples while maintaining a perspective of different learner levels?
Prototype:
- The prototype needs to show abstraction and consider learner levels. The idea is to have a simple data set (Animal) and an OCS data set (Student / FantasyStudent) to solve both scenarios.
- Some implementations will go beyond College Board introductions. This includes all the inheritance and some of the functional programming to transform data. These elements need detailed comments.
Test: Here are test considerations to make Testing and Hacks more effective:
- Lesson presentation will be focused on highlights; mermaid diagrams have been created to reduce walls of text and clarify data flow vs. architecture.
- Code comments should be extensive and are used for self-help while doing homework and lab assignments.
- Hacks will provide scaffolded, multi-part challenges (from base attribute modeling to advanced registry queries) that empower students to build real-world data structures step-by-step while offering clear milestones for evaluation and AI link submission.