adgadev/jplusone

View on GitHub
jplusone-core/src/main/java/com/adgadev/jplusone/core/report/SessionFormatter.java

Summary

Maintainability
B
6 hrs
Test Coverage
/*
 * Copyright (c) 2020 Adam Gaj
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.adgadev.jplusone.core.report;

import com.adgadev.jplusone.core.frame.FrameExtract;
import com.adgadev.jplusone.core.registry.LazyInitialisation;
import com.adgadev.jplusone.core.registry.OperationNodeView;
import com.adgadev.jplusone.core.registry.OperationType;
import com.adgadev.jplusone.core.registry.SessionNodeView;
import com.adgadev.jplusone.core.registry.StatementNodeView;
import com.adgadev.jplusone.core.registry.StatementType;
import lombok.RequiredArgsConstructor;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import static com.adgadev.jplusone.core.utils.CollectionUtils.getLastItemOfList;
import static com.adgadev.jplusone.core.utils.StreamUtils.filterToList;

@RequiredArgsConstructor
public class SessionFormatter {

    private static final String NEWLINE = "\n";

    private static String INDENT = "    ";

    private static final Map<Integer, String> INDENTS = Map.of(
            1, INDENT,
            2, INDENT + INDENT,
            3, INDENT + INDENT + INDENT,
            4, INDENT + INDENT + INDENT + INDENT,
            5, INDENT + INDENT + INDENT + INDENT + INDENT,
            6, INDENT + INDENT + INDENT + INDENT + INDENT + INDENT,
            7, INDENT + INDENT + INDENT + INDENT + INDENT + INDENT + INDENT
    );

    private final Set<OperationType> visibleOperationsType;

    private final Set<StatementType> visibleStatementsType;

    private final boolean proxyCallFramesHidden;

    public String format(SessionNodeView session) {
        StringBuilder builder = new StringBuilder();
        builder.append(NEWLINE + INDENTS.get(1) + "ROOT");

        List<FrameExtract> sessionCallFrames = session.getSessionFrameStack().getCallFrames();

        for (FrameExtract frame : filterApplicationCallFrames(sessionCallFrames, proxyCallFramesHidden)) {
            if (frame.isNotThirdPartyClass()) {
                builder.append(NEWLINE + INDENTS.get(2));
                builder.append(frame.format());
            }
        }

        builder.append(NEWLINE + INDENTS.get(3) + "SESSION BOUNDARY");

        for (OperationNodeView operation : session.getOperations()) {
            if (visibleOperationsType.contains(operation.getOperationType())
                    && containsAnyVisibleStatements(operation, visibleStatementsType)) {

                builder.append(NEWLINE + INDENTS.get(4) + "OPERATION [" + operation.getOperationType() + "]");
                List<FrameExtract> operationCallFrames = operation.getCallFramesStack().getCallFrames();

                for (FrameExtract frame : filterApplicationCallFrames(operationCallFrames, proxyCallFramesHidden)) {
                    if (frame.isNotThirdPartyClass()) {
                        builder.append(NEWLINE + INDENTS.get(5));
                        builder.append(frame.format());
                    }
                }

                for (LazyInitialisation lazyInitialisation: operation.getLazyInitialisations()) {
                    builder.append(NEWLINE + INDENTS.get(5) + lazyInitialisation);
                }

                for (StatementNodeView statement : operation.getStatements()) {
                    if (visibleStatementsType.contains(statement.getStatementType())) {
                        builder.append(NEWLINE + INDENTS.get(6) + "STATEMENT [" + statement.getStatementType().getStatementGroupType() + "]");
                        builder.append(SqlFormatter.formatSql(INDENTS.get(7), statement.getSql()));
                    }
                }
            }
        }

        return builder.toString();
    }

    private boolean containsAnyVisibleStatements(OperationNodeView operation, Set<StatementType> visibleStatementsType) {
        return operation.getStatements().stream()
                .filter(statementNode -> visibleStatementsType.contains(statementNode.getStatementType()))
                .findFirst()
                .isPresent();
    }

    private List<FrameExtract> filterApplicationCallFrames(List<FrameExtract> callFrames, boolean proxyCallFramesHidden) {
        List<FrameExtract> applicationAllCallFrames = filterToList(callFrames, FrameExtract::isNotThirdPartyClass);

        if (!proxyCallFramesHidden) {
            return applicationAllCallFrames;
        } else {
            List<FrameExtract> result = filterToList(applicationAllCallFrames, FrameExtract::isApplicationClass);

            if (!applicationAllCallFrames.isEmpty()) {
                Optional<FrameExtract> lastApplicationCallFrame = getLastItemOfList(applicationAllCallFrames);
                Optional<FrameExtract> lastApplicationClassCallFrame = getLastItemOfList(result);

                if (lastApplicationCallFrame.isPresent() && !lastApplicationCallFrame.equals(lastApplicationClassCallFrame)) {
                    result.add(lastApplicationCallFrame.get());
                }
            }

            return result;
        }
    }
}