All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cdc.mf.model.MfElement Maven / Gradle / Ivy

The newest version!
package cdc.mf.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;

import cdc.issues.Metas;
import cdc.issues.locations.LocatedItem;
import cdc.util.lang.Introspection;
import cdc.util.strings.StringUtils;

/**
 * Base interface of all model elements.
 * 

* They can all have an identifier and be documented. * * @author Damien Carbonne */ public interface MfElement extends MfMetasItem, LocatedItem { public static final Comparator ID_COMPARATOR = Comparator.comparing(x -> x.getId() == null ? "" : x.getId()); public boolean canWrap(); public boolean canWrap(Class wrapperClass); public W wrap(Class wrapperClass); public default String getKind() { return MfUtils.getKind(this); } public default String getCode() { return MfUtils.getCode(this); } /** * @return The identifier of this element. * Some elements must have an identifier, others may (but not necessarily) have one. */ public String getId(); public default boolean hasId() { return !StringUtils.isNullOrEmpty(getId()); } public String getGuid(); public default boolean hasGuid() { return !StringUtils.isNullOrEmpty(getGuid()); } /** * @return The parent element of this element, possibly {@code null}. */ public MfElement getParent(); public default boolean hasParent() { return getParent() != null; } /** * @return The first ancestor that is a package, possibly {@code null}. */ public default MfPackage getSurroundingPackage() { if (getParent() instanceof final MfPackage p) { return p; } else if (hasParent()) { return getParent().getSurroundingPackage(); } else { return null; } } /** * @return The top level ancestor that is a package, possibly {@code null}. */ public default MfPackage getRootPackage() { MfPackage p = getSurroundingPackage(); if (p == null) { return null; } else { while (p.getParent() instanceof final MfPackage parent) { p = parent; } return p; } } /** * @return The depth (1 for root element) of the element. */ public default int getDepth() { int depth = 0; MfElement index = this; while (index != null) { index = index.getParent(); depth++; } return depth; } /** * @return A list of ancestors. */ public default List getHierarchy() { final List list = new ArrayList<>(); MfElement iter = this; while (iter != null) { list.add(iter); iter = iter.getParent(); } Collections.reverse(list); return list; } /** * @return The index of this element among the children of its parent. * {@code -1} if this element has no parent. */ public int getIndex(); public default List getIndices() { final List list = new ArrayList<>(); MfElement iter = this; while (iter != null && iter.getIndex() >= 0) { list.add(iter.getIndex()); iter = iter.getParent(); } Collections.reverse(list); return list; } public default MfLocationPart getLocationPart() { return MfLocationPart.of(this); } @Override default MfLocation getLocation() { return MfLocation.of(this); } /** * @param

The parent type. * @param parentClass The parent class. * @return The parent element (the owner) of this element, * possibly {@code null} or converted to {@code parentClass}. * @throws ClassCastException When the parent can not be converted to {@code parentClass}. */ public default

P getParent(Class

parentClass) { return parentClass.cast(getParent()); } /** * @return A list of locally owned children of this element. */ public List getChildren(); /** * @param The child type. * @param childClass The child class. * @return A list of locally owned children that are instances of {@code childClass}. */ public default List getChildren(Class childClass) { return getChildren().stream() .filter(childClass::isInstance) .map(childClass::cast) .toList(); } /** * @param The child type. * @param childClass The child class. * @param predicate The predicate. * @return A list of locally owned children that are instances of {@code childClass} and match {@code predicate}. */ public default List getChildren(Class childClass, Predicate predicate) { return getChildren().stream() .filter(childClass::isInstance) .map(childClass::cast) .filter(predicate) .toList(); } /** * @param name The child name. * @return A list of locally owned children named {@code name}. */ public default List getChildren(String name) { return getChildren().stream() .filter(MfNameItem.class::isInstance) .map(MfNameItem.class::cast) .filter(x -> Objects.equals(name, x.getName())) .toList(); } public default Optional getFirstChild(Class childClass, Predicate predicate) { return getChildren().stream() .filter(childClass::isInstance) .map(childClass::cast) .filter(predicate) .findFirst(); } /** * @param The child type. * @param childClass The child class. * @return The (first) child of this element that is an instance of {@code childClass}. * @throws NoSuchElementException When there are no matching children. */ public default C getChild(Class childClass) { return getChildren().stream() .filter(childClass::isInstance) .map(childClass::cast) .findFirst() .orElseThrow(); } /** * @param The child type. * @param childClass The child class. * @return {@code true} if this element has {@code childClass} children. */ public default boolean hasChildren(Class childClass) { return getChildren().stream() .anyMatch(childClass::isInstance); } /** * @param The child type. * @param name The child name. * @param childClass The child class. * @return The (first) child of this element that is an instance of {@code childClass} * and is named {@code name}. * @throws NoSuchElementException When there is no matching child. * @throws ClassCastException When the child can not be converted to {@code childClass}. */ public C getChild(String name, Class childClass); public default MfElement getChild(MfLocationPart lp) { return MfLocationPart.getChild(this, lp); } /** * @return The {@link MfModel} of this element. */ public MfModel getModel(); /** * @return A list of {@link MfDocumentation documentations} locally owned by this element. */ public default List getDocumentations() { return getChildren(MfDocumentation.class); } /** * @return {@code true} if this element locally owns {@link MfDocumentation documentations}. */ public default boolean hasDocumentations() { return hasChildren(MfDocumentation.class); } /** * @return A {@link MfDocumentation documentation} {@link MfDocumentation.Builder builder}. */ public MfDocumentation.Builder documentation(); /** * @return A list of {@link MfLink links} locally owned by this element. */ public default List> getLinks() { return getChildren(Introspection.uncheckedCast(MfLink.class)); } /** * @param The link type. * @param cls The link class. * @return A list of {@link MfLink links} locally owned by this element and are instance of {@code cls}. */ public default > List getLinks(Class cls) { return getLinks().stream() .filter(cls::isInstance) .map(cls::cast) .toList(); } /** * @return A list of {@link MfLink links} whose target is directly this element. */ public List> getReversedLinks(); /** * @param The link type. * @param cls The link class. * @return A List of {@link MfLink MfLinks} that are instances of {@code cls} * and where this element is target. */ public default > List getReversedLinks(Class cls) { return getReversedLinks().stream() .filter(cls::isInstance) .map(cls::cast) .toList(); } /** * Traverses all elements and invokes a consumer on elements that match a class and predicate. * * @param The element type. * @param elementClass The element class. * @param consumer The element consumer. * @param predicate The element predicate. */ public default void traverse(Class elementClass, Consumer consumer, Predicate predicate) { if (elementClass.isInstance(this)) { final E x = elementClass.cast(this); if (predicate.test(x)) { consumer.accept(x); } } for (final MfElement child : getChildren()) { child.traverse(elementClass, consumer, predicate); } } /** * Traverses all elements and invokes a consumer on elements that match a class. * * @param The element type. * @param elementClass The element class. * @param consumer The element consumer. */ public default void traverse(Class elementClass, Consumer consumer) { traverse(elementClass, consumer, x -> true); } /** * Traverses all elements and invokes a consumer on each traversed element. * * @param consumer The element consumer. */ public default void traverse(Consumer consumer) { traverse(MfElement.class, consumer); consumer.accept(this); } /** * @param The element type. * @param elementClass The element class. * @param predicate The element predicate. * @return A List of all elements that are instances of {@code elementClass} and match {@code predicate}. */ public default List collect(Class elementClass, Predicate predicate) { final List list = new ArrayList<>(); traverse(elementClass, list::add, predicate); return list; } /** * @param The element type. * @param elementClass The element class. * @return A List of all elements that are instances of {@code elementClass}. */ public default List collect(Class elementClass) { return collect(elementClass, x -> true); } public static interface Builder, E extends MfElement> { /** * @return The built class. */ public Class getElementClass(); public B set(E element); /** * @return The id. */ public String getId(); /** * Sets the identifier. * * @param id The identifier. * @return This builder. */ public B id(String id); /** * @return The GUID. */ public String getGuid(); /** * Sets the GUID. * * @param guid The GUID. * @return This builder. */ public B guid(String guid); public Metas getMetas(); /** * Adds a (name, value) meta. * * @param name The name. * @param value The value. * @return This builder. */ public B meta(String name, String value); public B meta(String name, String value, String separator); public B metas(Metas metas); /** * Adds a (name, value) meta. * * @param name The name. * @param value The value. * @return This builder. */ public B meta(MfEnum name, String value); public B meta(MfEnum name, String value, String separator); /** * @return The built element. */ public E build(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy