com.spectralogic.ds3autogen.c.helpers.StructHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.spectralogic.ds3autogen.c.helpers.StructHelper.java

Source

/*
 * ******************************************************************************
 *   Copyright 2014-2015 Spectra Logic Corporation. All Rights Reserved.
 *   Licensed under the Apache License, Version 2.0 (the "License"). You may not use
 *   this file except in compliance with the License. A copy of the License is located at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 *   or in the "license" file accompanying this file.
 *   This file 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.spectralogic.ds3autogen.c.helpers;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.spectralogic.ds3autogen.c.models.Struct;
import com.spectralogic.ds3autogen.c.models.StructMember;
import com.spectralogic.ds3autogen.utils.Helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

import static com.spectralogic.ds3autogen.utils.Helper.indent;

public final class StructHelper {
    private static final Logger LOG = LoggerFactory.getLogger(StructHelper.class);

    private StructHelper() {
    }

    private final static StructHelper structHelper = new StructHelper();

    public static StructHelper getInstance() {
        return structHelper;
    }

    public static String getNameUnderscores(final String name) {
        return Helper.camelToUnderscore(Helper.removeTrailingRequestHandler(Helper.unqualifiedName(name)));
    }

    public static String getDs3TypeName(final String name) {
        final String name_underscores = getNameUnderscores(name);
        if (name_underscores.startsWith("ds3_")) { // some special-cased types have already been renamed with ds3_ prefix
            return name_underscores;
        }
        return "ds3_" + name_underscores;
    }

    public static String getResponseTypeName(final String name) {
        return getDs3TypeName(name) + "_response";
    }

    public static String getParserFunctionName(final String ds3TypeName) {
        return "_parse_" + ds3TypeName;
    }

    public static String getXmlTag(final StructMember structMember) {
        if (structMember.hasWrapper() || structMember.getName().equals("common_prefixes")) {
            return structMember.getEncapsulatingTag();
        }
        return Helper.capFirst(structMember.getNameToMarshall());
    }

    /**
     * Determine if a parser requires a ds3_error to track the response of a sub-parser
     */
    public static boolean hasComplexMembers(final Struct struct) {
        for (final StructMember structMember : struct.getStructMembers()) {
            if (!structMember.getType().isPrimitive()) {
                if (structMember.getType().getTypeName().equals("ds3_str"))
                    continue; // ds3_str is not an auto-generated API typeName.

                return true;
            } else if (structMember.getType().isArray()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Determine if a Struct has any StructMembers which need to be parsed as an attribute
     */
    public static boolean hasAttributes(final Struct structEntry) {
        return structEntry.getStructMembers().stream().anyMatch(StructMember::isAttribute);
    }

    /**
     * Determine if a Struct has any StructMembers which need to be parsed as a child-node
     */
    public static boolean hasChildNodes(final Struct structEntry) {
        return structEntry.getStructMembers().stream().anyMatch(sm -> !sm.isAttribute());
    }

    /**
     * Determine if any array StructMembers are not wrapped in an enclosing tag:
     * <Objects ID="some_id">
     *     <Object name="obj1"></Object>
     * </Objects>
     */
    public static boolean hasUnwrappedChildNodes(final Struct structEntry) {
        return structEntry.getStructMembers().stream()
                .filter(sm -> !sm.getType().getTypeName().equals("ds3_tape_type")) // enum list
                .filter(sm -> !sm.getType().getTypeName().equals("ds3_tape_drive_type")) // enum list
                .anyMatch(sm -> (!sm.isAttribute() && sm.hasWrapper()));
    }

    /**
     * Determine if a Struct requires a custom parser.
     */

    public static boolean requiresNewCustomParser(final Struct struct, final Set<String> existingTypes,
            final ImmutableSet<String> enumNames) {
        for (final StructMember member : struct.getStructMembers()) {
            if (!member.getType().isPrimitive()) {
                if (member.getType().getTypeName().equals("ds3_str"))
                    continue; // ds3_str is not an auto-generated API typeName.

                if (member.getType().getTypeName().equals("ds3_paging"))
                    continue; // ds3_paging is not an auto-generated API typeName.

                if (existingTypes.contains(member.getType().getTypeName()))
                    continue;

                if (enumNames.contains(member.getType().getTypeName()))
                    continue;

                LOG.warn("Unknown type[" + member.getType().getTypeName() + "]");
                return true;
            }
        }
        return false;
    }

    /**
     * Return Structs which contain only primitive types first, and then cascade for Complex Structs that contain other Structs
     *
     * @throws java.text.ParseException
     */
    public static ImmutableList<Struct> getStructsOrderedList(final ImmutableList<Struct> allStructs,
            final ImmutableSet<String> enumNames) throws ParseException {
        final Queue<Struct> structsQueue = new LinkedList<>(allStructs);
        final Set<String> existingStructs = new HashSet<>();
        final ImmutableList.Builder<Struct> orderedStructsBuilder = ImmutableList.builder();
        int skippedStructsCount = 0;
        while (!structsQueue.isEmpty()) {
            final int structsQueueSize = structsQueue.size();
            final Struct structEntry = structsQueue.remove();

            if (!StructHelper.requiresNewCustomParser(structEntry, existingStructs, enumNames)) {
                existingStructs.add(structEntry.getName());
                LOG.info(structEntry.toString());
                orderedStructsBuilder.add(structEntry);
            } else { // move to end to come back to
                structsQueue.add(structEntry);
            }

            if (structsQueueSize == structsQueue.size()) {
                skippedStructsCount++;
                if (skippedStructsCount == structsQueueSize) {
                    LOG.warn("Unable to progress on remaining structs, aborting!");
                    LOG.warn("  Remaining structs[" + structsQueue.size() + "]");
                    for (final Struct struct : allStructs) {
                        LOG.warn("    " + struct.toString() + "\n");
                    }
                    throw new ParseException("Unable to Order provided structs.", 0);
                }
            } else {
                skippedStructsCount = 0;
            }
        }

        return orderedStructsBuilder.build();
    }

    public static String generateResponseParser(final String structName,
            final ImmutableList<StructMember> structMembers) throws ParseException {
        boolean firstElement = true;
        final StringBuilder outputBuilder = new StringBuilder();

        for (int structMemberIndex = 0; structMemberIndex < structMembers.size(); structMemberIndex++) {
            final StructMember currentStructMember = structMembers.get(structMemberIndex);
            if (currentStructMember.isAttribute())
                continue; // only parsing child nodes for a specific node
            if (currentStructMember.getName().startsWith("num_"))
                continue; // skip - these are used for array iteration and are not a part of the response
            if (currentStructMember.getName().equals("paging"))
                continue; // skip - parsed from pagination headers

            outputBuilder.append(indent(2));

            if (!firstElement) {
                outputBuilder.append("} else ");
            } else {
                firstElement = false;
            }

            outputBuilder.append("if (element_equal(child_node, \"").append(getXmlTag(currentStructMember))
                    .append("\")) {").append("\n");
            outputBuilder.append(StructMemberHelper.getParseStructMemberBlock(currentStructMember));
        }

        outputBuilder.append(indent(2)).append("} else {").append("\n");
        outputBuilder.append(indent(3)).append("ds3_log_message(client->log, DS3_ERROR, \"Unknown node[%s] of "
                + structName + " [%s]\\n\", child_node->name, root->name);").append("\n");
        outputBuilder.append(indent(2)).append("}").append("\n");
        outputBuilder.append("\n");
        outputBuilder.append(indent(2)).append("if (error != NULL) {\n");
        outputBuilder.append(indent(3)).append("break;\n");
        outputBuilder.append(indent(2)).append("}\n");

        return outputBuilder.toString();
    }

    public static String generateResponseAttributesParser(final String structName,
            final ImmutableList<StructMember> structMembers) throws ParseException {
        boolean firstElement = true;
        final StringBuilder outputBuilder = new StringBuilder();

        for (int structMemberIndex = 0; structMemberIndex < structMembers.size(); structMemberIndex++) {
            final StructMember currentStructMember = structMembers.get(structMemberIndex);
            if (!currentStructMember.isAttribute())
                continue; // only parsing attributes for a specific node

            outputBuilder.append(indent(2));

            if (!firstElement) {
                outputBuilder.append("} else ");
            } else {
                firstElement = false;
            }

            outputBuilder.append("if (attribute_equal(attribute, \"")
                    .append(Helper.capFirst(currentStructMember.getNameToMarshall())).append("\") == true) {")
                    .append("\n");
            outputBuilder.append(StructMemberHelper.getParseStructMemberAttributeBlock(currentStructMember));
        }

        outputBuilder.append(indent(2)).append("} else {").append("\n");
        outputBuilder.append(indent(3)).append("ds3_log_message(client->log, DS3_ERROR, \"Unknown attribute[%s] of "
                + structName + " [%s]\\n\", attribute->name, root->name);").append("\n");
        outputBuilder.append(indent(2)).append("}").append("\n");
        outputBuilder.append("\n");
        outputBuilder.append(indent(2)).append("if (error != NULL) {\n");
        outputBuilder.append(indent(3)).append("break;\n");
        outputBuilder.append(indent(2)).append("}\n");

        return outputBuilder.toString();
    }
}