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

Java tutorial

Introduction

Here is the source code for com.spectralogic.ds3autogen.c.helpers.StructMemberHelper.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.spectralogic.ds3autogen.c.models.StructMember;
import com.spectralogic.ds3autogen.utils.Helper;
import com.spectralogic.ds3autogen.utils.collections.GuavaCollectors;

import java.text.ParseException;

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

public final class StructMemberHelper {
    private StructMemberHelper() {
    }

    private final static StructMemberHelper structMemberHelper = new StructMemberHelper();

    public static StructMemberHelper getInstance() {
        return structMemberHelper;
    }

    public static ImmutableList<StructMember> getWrappedListChildNodes(
            final ImmutableList<StructMember> structMembers) {
        return structMembers.stream().filter(sm -> sm.getType().isArray()).filter(StructMember::hasWrapper)
                .collect(GuavaCollectors.immutableList());
    }

    /**
     * Used by ResponseParse.ftl and ResponseParserTopLevel.ftl
     */
    public static ImmutableList<StructMember> getUnwrappedListChildNodes(
            final ImmutableList<StructMember> structMembers) {
        return structMembers.stream().filter(sm -> sm.getType().isArray()).filter(sm -> !sm.hasWrapper())
                .filter(sm -> !sm.getType().getTypeName().equals("ds3_tape_type")) // enum list
                .filter(sm -> !sm.getType().getTypeName().equals("ds3_tape_drive_type")) // enum list
                .collect(GuavaCollectors.immutableList());
    }

    public static String generateStructMemberParserLine(final StructMember structMember,
            final String parserFunction) throws ParseException {
        return indent(3) + "response->" + Helper.camelToUnderscore(structMember.getName()) + " = " + parserFunction
                + "\n";
    }

    /**
     * Also applies to any element whose CollectionValueRenderingMode is "BLOCK_FOR_EVERY_ELEMENT"
     */
    public static String generateStructMemberDs3StrArrayBlock(final StructMember structMember) {
        return indent(3) + "xmlNodePtr loop_node;\n" + indent(3) + "GPtrArray* " + structMember.getName()
                + "_array = g_ptr_array_new();\n" + indent(3) + "int num_nodes = 0;\n" + indent(3)
                + "for (loop_node = child_node->xmlChildrenNode; loop_node != NULL; loop_node = loop_node->next, num_nodes++) {\n"
                + indent(4) + structMember.getType().getTypeName() + "* " + structMember.getName()
                + " = xml_get_string(doc, loop_node);\n" + indent(4) + "g_ptr_array_add(" + structMember.getName()
                + "_array, " + structMember.getName() + ");\n" + indent(3) + "}\n" + indent(3) + "response->"
                + structMember.getName() + " = (" + structMember.getType().getTypeName() + "**)"
                + structMember.getName() + "_array->pdata;\n" + indent(3) + "response->num_"
                + structMember.getName() + " = " + structMember.getName() + "_array->len;\n" + indent(3)
                + "g_ptr_array_free(" + structMember.getName() + "_array, FALSE);\n";
    }

    /**
     * Only applies to CommonPrefixes in ListBucketResult and ListMultipartUploadsResult
     */
    public static String generateStructMemberUnwrappedDs3StrArrayBlock(final StructMember structMember) {
        return indent(3) + "xmlNodePtr loop_node;\n" + indent(3) + "int num_nodes = 0;\n" + indent(3)
                + "for (loop_node = child_node->xmlChildrenNode; loop_node != NULL; loop_node = loop_node->next, num_nodes++) {\n"
                + indent(4) + structMember.getType().getTypeName() + "* " + structMember.getName()
                + " = xml_get_string(doc, loop_node);\n" + indent(4) + "g_ptr_array_add(" + structMember.getName()
                + "_array, " + structMember.getName() + ");\n" + indent(3) + "}\n";
    }

    public static String generateStructMemberArrayParserBlock(final StructMember structMember)
            throws ParseException {
        return indent(3) + "GPtrArray* " + structMember.getName() + "_array;\n" + indent(3) + "error = _parse_"
                + structMember.getType().getTypeName() + "_array(client, doc, child_node, &"
                + structMember.getName() + "_array);\n" + indent(3) + "response->" + structMember.getName() + " = ("
                + structMember.getType().getTypeName() + "**)" + structMember.getName() + "_array->pdata;\n"
                + indent(3) + "response->num_" + structMember.getName() + " = " + structMember.getName()
                + "_array->len;\n" + indent(3) + "g_ptr_array_free(" + structMember.getName() + "_array, FALSE);\n";
    }

    public static String generateUnwrappedStructMemberArrayParserBlock(final StructMember structMember)
            throws ParseException {
        return indent(3) + structMember.getType().getTypeName() + "* " + structMember.getName()
                + "_response = NULL;\n" + indent(3) + "error = _parse_" + structMember.getType().getTypeName()
                + "(client, doc, child_node, &" + structMember.getName() + "_response);\n" + indent(3)
                + "response->" + structMember.getName() + " = (" + structMember.getType().getTypeName() + "**)"
                + structMember.getName() + "_array->pdata;\n" + indent(3) + "g_ptr_array_add("
                + structMember.getName() + "_array, " + structMember.getName() + "_response);\n";
    }

    public static String generateStructMemberEnumParserBlock(final StructMember structMember) {
        return indent(3) + "xmlChar* text = xmlNodeListGetString(doc, child_node, 1);\n" + indent(3)
                + "if (text == NULL) {\n" + indent(4) + "continue;\n" + indent(3) + "}\n" + indent(3) + "response->"
                + structMember.getName() + " = _match_" + structMember.getType().getTypeName()
                + "(client->log, text);\n" + indent(3) + "xmlFree(text);\n";
    }

    public static String generateStructMemberEnumAttributeParserBlock(final StructMember structMember) {
        return indent(3) + "xmlChar* text = xmlNodeListGetString(doc, attribute->children, 1);\n" + indent(3)
                + "if (text == NULL) {\n" + indent(4) + "continue;\n" + indent(3) + "}\n" + indent(3) + "response->"
                + structMember.getName() + " = _match_" + structMember.getType().getTypeName()
                + "(client->log, text);\n" + indent(3) + "xmlFree(text);\n";
    }

    public static String generateStructMemberEnumArrayParserBlock(final StructMember structMember) {
        return indent(3) + "xmlNodePtr loop_node;\n" + indent(3) + "int num_nodes = 0;\n" + indent(3)
                + "GByteArray* enum_array = g_byte_array_new();\n" + indent(3)
                + structMember.getType().getTypeName() + " " + structMember.getName() + ";\n" + indent(3)
                + "for (loop_node = child_node->xmlChildrenNode; loop_node != NULL; loop_node = loop_node->next, num_nodes++) {\n"
                + indent(4) + "xmlChar* text = xmlNodeListGetString(doc, loop_node, 1);\n" + indent(4)
                + "if (text == NULL) {\n" + indent(5) + "continue;\n" + indent(4) + "}\n" + indent(4)
                + structMember.getName() + " = _match_" + structMember.getType().getTypeName()
                + "(client->log, text);\n" + indent(4) + "g_byte_array_append(enum_array, (const guint8*) &"
                + structMember.getName() + ", sizeof(" + structMember.getType().getTypeName() + "));\n" + indent(3)
                + "}\n" + indent(3) + "response->" + structMember.getName() + " = ("
                + structMember.getType().getTypeName() + "*)enum_array->data;\n" + indent(3) + "response->num_"
                + structMember.getName() + " = enum_array->len;\n" + indent(3)
                + "g_byte_array_free(enum_array, FALSE);\n";
    }

    public static String getParseStructMemberBlock(final StructMember structMember) throws ParseException {
        if (structMember.getType().isPrimitive() || structMember.getType().getTypeName().equals("ds3_tape_type")
                || structMember.getType().getTypeName().equals("ds3_tape_drive_type")) {
            switch (structMember.getType().getTypeName()) {
            case "uint64_t":
            case "size_t":
            case "double":
            case "float":
            case "long":
                return generateStructMemberParserLine(structMember, "xml_get_uint64(doc, child_node);");
            case "int":
                return generateStructMemberParserLine(structMember, "xml_get_uint16(doc, child_node);");
            case "ds3_bool":
                // TODO c_sdk inconsistent: xml_get_bool is the only func to log a parse error
                return generateStructMemberParserLine(structMember, "xml_get_bool(client->log, doc, child_node);");
            default: // Enum
                if (structMember.getType().isArray()) {
                    return generateStructMemberEnumArrayParserBlock(structMember);
                }
                return generateStructMemberEnumParserBlock(structMember);
            }
        } else if (structMember.getType().getTypeName().equals("ds3_str")) { // special case
            if (structMember.getName().equals("common_prefixes")) {
                return generateStructMemberUnwrappedDs3StrArrayBlock(structMember);
            }
            if (structMember.getType().isArray()) {
                return generateStructMemberDs3StrArrayBlock(structMember);
            }
            return generateStructMemberParserLine(structMember, "xml_get_string(doc, child_node);");
        } else if (structMember.getType().isArray()) {
            if (structMember.hasWrapper()) {
                return generateStructMemberArrayParserBlock(structMember);
            }
            return generateUnwrappedStructMemberArrayParserBlock(structMember);
        }

        return indent(3) + "error = " + StructHelper.getParserFunctionName(structMember.getType().getTypeName())
                + "(client, doc, child_node, &response->" + structMember.getName() + ");\n";
    }

    public static String getParseStructMemberAttributeBlock(final StructMember structMember) throws ParseException {
        if (structMember.getType().isPrimitive()) {
            switch (structMember.getType().getTypeName()) {
            case "uint64_t":
            case "size_t":
            case "double":
            case "float":
            case "long":
                return generateStructMemberParserLine(structMember,
                        "xml_get_uint64_from_attribute(doc, attribute);");
            case "int":
                return generateStructMemberParserLine(structMember,
                        "xml_get_uint16_from_attribute(doc, attribute);");
            case "ds3_bool":
                // TODO c_sdk inconsistent: xml_get_bool is the only func to log a parse error
                return generateStructMemberParserLine(structMember,
                        "xml_get_bool_from_attribute(client->log, doc, attribute);");
            default: // Enum
                if (structMember.getType().isArray()) {
                    throw new IllegalArgumentException(
                            "Attribute " + structMember.getType().getTypeName() + " is an array");
                }
                return generateStructMemberEnumAttributeParserBlock(structMember);
            }
        } else if (structMember.getType().getTypeName().equals("ds3_str")) { // special case
            if (structMember.getType().isArray()) {
                throw new IllegalArgumentException(
                        "Attribute " + structMember.getType().getTypeName() + " is an array");
            }
            return generateStructMemberParserLine(structMember, "xml_get_string_from_attribute(doc, attribute);");
        } else if (structMember.getType().isArray()) {
            return generateStructMemberArrayParserBlock(structMember);
        }

        throw new IllegalArgumentException(
                "Attribute " + structMember.getType().getTypeName() + " is a complex (DS3) type");
    }

    public static String generateFreeArrayStructMember(final StructMember structMember) {
        return indent(1) + "for (index = 0; index < response->num_" + structMember.getName() + "; index++) {\n"
                + indent(2) + structMember.getType().getTypeName() + "_free(response->" + structMember.getName()
                + "[index]);\n" + indent(1) + "}\n" + indent(1) + "g_free(response->" + structMember.getName()
                + ");\n";
    }

    public static String generateFreeStructMembers(final ImmutableList<StructMember> structMembers)
            throws ParseException {
        final StringBuilder outputBuilder = new StringBuilder();

        for (final StructMember structMember : structMembers) {
            if (structMember.getType().isPrimitive()) { // PrimitiveTypes only need to free the base pointer
                if (structMember.getType().isArray()) {
                    outputBuilder.append(indent(1)).append("g_free(response->").append(structMember.getName())
                            .append(");\n");
                }
                // else do nothing for single PrimitiveType
            } else if (structMember.getType().isArray()) { // FreeableType needs to free each element
                outputBuilder.append(generateFreeArrayStructMember(structMember));
            } else {
                outputBuilder.append(indent(1)).append(structMember.getType().getTypeName())
                        .append("_free(response->").append(structMember.getName()).append(");\n");
            }
        }

        return outputBuilder.toString();
    }

    public static String generateStructMembers(final ImmutableList<StructMember> structMembers)
            throws ParseException {
        final StringBuilder outputBuilder = new StringBuilder();

        for (final StructMember member : structMembers) {
            outputBuilder.append(indent(1)).append(member.getType()).append(" ").append(member.getName())
                    .append(";\n");
        }

        return outputBuilder.toString();
    }
}