001package systems.dmx.core.impl;
002
003import systems.dmx.core.model.AssociationDefinitionModel;
004import systems.dmx.core.model.ChildTopicsModel;
005import systems.dmx.core.model.DMXObjectModel;
006
007import java.util.List;
008import java.util.logging.Logger;
009
010
011
012class ChildTopicsFetcher {
013
014    // ---------------------------------------------------------------------------------------------- Instance Variables
015
016    private PersistenceLayer pl;
017
018    private Logger logger = Logger.getLogger(getClass().getName());
019
020    // ---------------------------------------------------------------------------------------------------- Constructors
021
022    ChildTopicsFetcher(PersistenceLayer pl) {
023        this.pl = pl;
024    }
025
026    // ----------------------------------------------------------------------------------------- Package Private Methods
027
028    /**
029     * Fetches the child topic models (recursively) of the given object model and updates it in-place.
030     * ### TODO: recursion is required in some cases (e.g. when fetching a topic through REST API) but is possibly
031     * overhead in others (e.g. when updating composite structures).
032     * <p>
033     * Works for both, "one" and "many" association definitions.
034     *
035     * @param   assocDef    The child topic models according to this association definition are fetched.
036     */
037    void fetch(DMXObjectModel object, AssociationDefinitionModel assocDef, boolean deep) {
038        try {
039            ChildTopicsModel childTopics = object.getChildTopicsModel();
040            String cardinalityUri = assocDef.getChildCardinalityUri();
041            String assocDefUri    = assocDef.getAssocDefUri();
042            if (cardinalityUri.equals("dmx.core.one")) {
043                RelatedTopicModelImpl childTopic = fetchChildTopic(object.getId(), assocDef);
044                // Note: topics just created have no child topics yet
045                if (childTopic != null) {
046                    childTopics.put(assocDefUri, childTopic);
047                    if (deep) {
048                        fetchChildTopics(childTopic, deep);    // recursion
049                    }
050                }
051            } else if (cardinalityUri.equals("dmx.core.many")) {
052                for (RelatedTopicModelImpl childTopic : fetchChildTopics(object.getId(), assocDef)) {
053                    childTopics.add(assocDefUri, childTopic);
054                    if (deep) {
055                        fetchChildTopics(childTopic, deep);    // recursion
056                    }
057                }
058            } else {
059                throw new RuntimeException("\"" + cardinalityUri + "\" is an unexpected cardinality URI");
060            }
061        } catch (Exception e) {
062            throw new RuntimeException("Fetching the \"" + assocDef.getAssocDefUri() + "\" child topics of object " +
063                object.getId() + " failed", e);
064        }
065    }
066
067    // ------------------------------------------------------------------------------------------------- Private Methods
068
069    /**
070     * Fetches the child topic models (recursively) of the given object model and updates it in-place.
071     * ### TODO: recursion is required in some cases (e.g. when fetching a topic through REST API) but is possibly
072     * overhead in others (e.g. when updating composite structures).
073     */
074    private void fetchChildTopics(DMXObjectModelImpl object, boolean deep) {
075        for (AssociationDefinitionModel assocDef : object.getType().getAssocDefs()) {
076            fetch(object, assocDef, deep);
077        }
078    }
079
080    // ---
081
082    /**
083     * Fetches and returns a child topic or <code>null</code> if no such topic extists.
084     */
085    private RelatedTopicModelImpl fetchChildTopic(long objectId, AssociationDefinitionModel assocDef) {
086        return pl.fetchRelatedTopic(
087            objectId,
088            assocDef.getInstanceLevelAssocTypeUri(),
089            "dmx.core.parent", "dmx.core.child",
090            assocDef.getChildTypeUri()
091        );
092    }
093
094    private List<RelatedTopicModelImpl> fetchChildTopics(long objectId, AssociationDefinitionModel assocDef) {
095        return pl.fetchRelatedTopics(
096            objectId,
097            assocDef.getInstanceLevelAssocTypeUri(),
098            "dmx.core.parent", "dmx.core.child",
099            assocDef.getChildTypeUri()
100        );
101    }
102}