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

org.nuiton.topia.templates.sql.TopiaMetadataEntityPathsBuilder Maven / Gradle / Ivy

There is a newer version: 10.0.1
Show newest version
package org.nuiton.topia.templates.sql;

/*-
 * #%L
 * Toolkit :: Templates
 * %%
 * Copyright (C) 2017 - 2024 Ultreia.io
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import com.google.common.collect.ArrayListMultimap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataAssociation;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataEntity;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataEntityPath;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataLink;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataModel;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataModelPaths;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataModelVisitor;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataOneToOneComposition;
import org.nuiton.topia.service.sql.metadata.TopiaMetadataReverseAssociation;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
import java.util.stream.Stream;

/**
 * To build {@link TopiaMetadataEntityPath} for a given type.
 * 

* Created on 20/08/15. * * @author Tony Chemit - [email protected] */ public class TopiaMetadataEntityPathsBuilder { private static final Logger log = LogManager.getLogger(TopiaMetadataEntityPathsBuilder.class); public static class Visitor extends TopiaMetadataModelVisitor.TopiaMetadataModelVisitorAdapter { private final ArrayListMultimap pathsBuilder; private final Deque stack; private final Deque paths; public Visitor() { this.pathsBuilder = ArrayListMultimap.create(); this.paths = new ArrayDeque<>(); this.stack = new ArrayDeque<>(); } @Override public void visitEntityStart(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity) { log.info("Start visit: " + metadataEntity); stack.offer(metadataEntity); } @Override public void visitEntityEnd(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity) { TopiaMetadataEntity poll = stack.poll(); log.info("End visit: " + poll); } @Override public void visitOneToOneAssociation(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity, String propertyName, TopiaMetadataEntity propertyType) { if (rejectAssociationType(metadataEntity, propertyName, propertyType)) { return; } registerPath(metadataModel, metadataEntity, propertyName, propertyType); } @Override public void visitOneToManyAssociation(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity, String propertyName, TopiaMetadataEntity propertyType) { if (rejectAssociationType(metadataEntity, propertyName, propertyType)) { return; } registerPath(metadataModel, metadataEntity, propertyName, propertyType); } @Override public void visitManyToManyAssociation(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity, String propertyName, TopiaMetadataEntity propertyType) { if (rejectAssociationType(metadataEntity, propertyName, propertyType)) { return; } registerPath(metadataModel, metadataEntity, propertyName, propertyType); } @Override public void visitManyToOneAssociation(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity, String propertyName, TopiaMetadataEntity propertyType) { if (rejectAssociationType(metadataEntity, propertyName, propertyType)) { return; } registerPath(metadataModel, metadataEntity, propertyName, propertyType); } @Override public void visitReversedAssociation(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity, String propertyName, TopiaMetadataEntity propertyType) { if (rejectReversedAssociationType(metadataEntity, propertyName, propertyType)) { return; } registerPath(metadataModel, metadataEntity, propertyName, propertyType); } protected boolean rejectReversedAssociationType(TopiaMetadataEntity metadataEntity, String propertyName, TopiaMetadataEntity propertyType) { return metadataEntity.isSkipNavigation(propertyName) || rejectType(propertyType); } protected boolean rejectAssociationType(TopiaMetadataEntity metadataEntity, String propertyName, TopiaMetadataEntity propertyType) { return metadataEntity.isSkipNavigation(propertyName) || rejectType(propertyType); } protected boolean rejectType(TopiaMetadataEntity propertyType) { return stack.contains(propertyType) || propertyType.isStandalone(); } protected void registerPath(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity, String propertyName, TopiaMetadataEntity propertyType) { log.info(String.format("Start to register new path from link: %s → %s", metadataEntity.getType(), propertyName)); TopiaMetadataLink link; { Stream candidates = metadataModel.getReverseOneToManyAssociations(propertyType).stream().filter(l -> l.getTargetPropertyName().equals(propertyName)); link = candidates.filter(l -> l.getOwner().equals(metadataEntity)).findFirst().orElse(null); } if (link == null) { Stream candidates = metadataModel.getReverseOneToOneAssociations(propertyType).stream().filter(l -> l.getTargetPropertyName().equals(propertyName)); link = candidates.filter(l -> l.getOwner().equals(metadataEntity)).findFirst().orElse(null); } if (link == null) { Stream candidates = metadataModel.getReverseAssociations(metadataEntity).stream().filter(l -> l.getTargetPropertyName().equals(propertyName)); link = candidates.filter(l -> l.getOwner().equals(metadataEntity)).findFirst().orElse(null); } if (link == null) { log.error(String.format("Can't find link for %s → %s", metadataEntity.getType(), propertyName)); } TopiaMetadataEntityPath parentPath = paths.peek(); TopiaMetadataEntityPath newPath = parentPath == null ? TopiaMetadataEntityPath.of(link) : parentPath.resolve(link); paths.offerFirst(newPath); try { propertyType.accept(this, metadataModel); } finally { TopiaMetadataEntityPath entityPath = Objects.requireNonNull(paths.poll()); pathsBuilder.put(entityPath.getEnd(), entityPath); log.warn(String.format("Register new path: %s", entityPath)); } } } public static TopiaMetadataModelPaths forEntryPoint(TopiaMetadataModelPaths all, TopiaMetadataEntity entryPoint) { TreeMap> entityPathsBuilder = new TreeMap<>(); for (Map.Entry> entry : all.asMap().entrySet()) { for (TopiaMetadataEntityPath path : entry.getValue()) { if (Objects.equals(entryPoint, path.getStart())) { entityPathsBuilder.put(entry.getKey(), List.of(path)); } } } return new TopiaMetadataModelPaths(entityPathsBuilder); } public static TopiaMetadataModelPaths forType(TopiaMetadataModelPaths all, TopiaMetadataEntity entryPoint) { TreeMap> entityPathsBuilder = new TreeMap<>(); for (Map.Entry> entry : all.asMap().entrySet()) { for (TopiaMetadataEntityPath path : entry.getValue()) { if (Objects.equals(entryPoint, path.getEnd())) { continue; } List links = new ArrayList<>(path.getLinks()); boolean match = false; Iterator iterator = links.iterator(); while (iterator.hasNext()) { TopiaMetadataLink link = iterator.next(); if (Objects.equals(entryPoint, link.getOwner())) { match = true; break; } iterator.remove(); } if (match) { entityPathsBuilder.put(entry.getKey(), List.of(new TopiaMetadataEntityPath(List.copyOf(links)))); } } } return new TopiaMetadataModelPaths(entityPathsBuilder); } public static TopiaMetadataModelPaths create(TopiaMetadataModel model) { TopiaMetadataEntityPathsBuilder builder = new TopiaMetadataEntityPathsBuilder(); TreeMap> entityPathsBuilder = new TreeMap<>(); model.streamWithEntryPoint().forEach(e -> { TreeMap> build = builder.build(model, e); entityPathsBuilder.putAll(build); }); return new TopiaMetadataModelPaths(entityPathsBuilder); } public TopiaMetadataEntityPathsBuilder() { } public TreeMap> build(TopiaMetadataModel metadataModel, TopiaMetadataEntity metadataEntity) { Visitor v = createVisitor(); v.visitModelStart(metadataModel); metadataEntity.accept(v, metadataModel); v.visitModelEnd(metadataModel); TreeMap> result = new TreeMap<>(); v.pathsBuilder.asMap().forEach((k, c) -> result.put(k, List.copyOf(c))); return result; } protected Visitor createVisitor() { return new Visitor(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy