Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Users to Traverse an Entity #14

Closed
dillonredding opened this issue Jan 12, 2023 · 0 comments · Fixed by #39
Closed

Allow Users to Traverse an Entity #14

dillonredding opened this issue Jan 12, 2023 · 0 comments · Fixed by #39
Assignees
Labels
enhancement New feature or request

Comments

@dillonredding
Copy link
Member

dillonredding commented Jan 12, 2023

An Entity could easily be traversed by implementing the Visitor pattern, allowing operations to be added to an entity graph without modifying the implementation. I believe this would also make implementing a Siren API crawler (#15) almost trivial.

Similar to this Java example, we could have something like the following:

export interface SirenElementVisitor {
  // need individual methods since JS/TS doesn't support overloading
  visitAction(action: Action): void;
  visitEmbeddedEntity(embeddedEntity: EmbeddedEntity): void;
  visitEmbeddedLink(embeddedLink: EmbeddedLink): void;
  visitEntity(entity: Entity): void;
  visitField(field: Field): void;
  visitLink(link: Link): void;
}

// each model class implements this interface
interface SirenElement {
  accept(visitor: SirenElementVisitor): void;
}

This requires each element to know how to traverse is child elements (not necessarily a bad thing). One advantage with this approach is that polymorphism handles distinguishing sub-entity types (no instanceof checks 😌).

Alternatively, instead of implementing SirenElement in each model, we could have a traverse function that understands how to traverse an entity.

function traverse(entity: Entity, visitor: SirenElementVisitor);

This fits well with the other top-level methods we have and has all the traversal logic, but the downside here is that we either need to manually distinguish between sub-entity types or have a generic visitSubEntity method, which will likely always have the boilerplate

if (subEntity instanceof EmbeddedLink) /* ... */ else /* ... */

The primary disadvantage of traverse is that you always have to start at the entity level, preventing users from (e.g.) creating an action-populating and submitting visitor.

Need to think more about the pros/cons of either approach, especially in regards to how async visits are handled (e.g., visitAction may call submit).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant