Metadata File Module

import raconverter

from raconverter.constants import *


class MetadataFile:
    """
    Create metadata file "Bilag 9" based on metadata files.
    The content of the metadata files originates from a data file of a suppored statistical program.
    """

    def __init__(self):
        self._entry_text = []

        # Instantiate class
        self.misc = raconverter.Misc()

    @property
    def entry_text(self):
        """
        Get internal list with entry text items.

        :return: A string with all entry text items combined
        """
        list_content = ['\n\n']

        # Add line breaks
        for item in self._entry_text:
            list_content.extend('%s\n' % item)
        # Convert list to string
        string_content = ''.join(list_content)

        return string_content

    @entry_text.setter
    def entry_text(self, entry_text):
        """
        Append entry text to a list.

        :param entry_text: Entry text
        """
        self._entry_text.append(entry_text)

    @entry_text.deleter
    def entry_text(self):
        """
        Reset list content.
        """
        self._entry_text = []

    def create_metadata_file(self, file_name):
        """
        Create the metadata file.

        :return: A list with entry text items
        """
        # Get metadata files
        metadata_files = self.get_metadata_files(file_name)
        # Get data file (output)
        data_file = ''.join([file_name, DATA])
        # Validate metadata files
        self.validate_metadata_files(metadata_files)
        # Validate corresponding data file
        self.validate_file(data_file)

        # Create metadata file content
        metadata_file_content = self.create_metadata_file_content(metadata_files)
        # Write metadata file content to file
        self.write_full_metadata_file(file_name, metadata_file_content)

        # Reset entry text
        entry_text = self.entry_text
        del self.entry_text

        return entry_text

    @staticmethod
    def get_metadata_files(file_name):
        """
        Add metadata file names to a list.

        :param file_name: The physical name of the data file without extension
        :return: A list with tuples containing metadata file names (key, value)
        """
        # Get metadata file name
        data_file_information = ''.join([file_name, DATA_FILE_INFORMATION_FILE])
        variable_list = ''.join([file_name, VARIABLE_LIST_FILE])
        variable_description = ''.join([file_name, VARIABLE_DESCRIPTION_FILE])
        code_list = ''.join([file_name, CODE_LIST_FILE])
        user_defined_missing_value = ''.join([file_name, USER_DEFINED_MISING_VALUE_FILE])

        metadata_files = [(DATA_FILE_INFORMATION_LABEL, data_file_information),
                          (VARIABLE_LIST_LABEL, variable_list),
                          (VARIABLE_DESCRIPTION_LABEL, variable_description),
                          (CODE_LIST_LABEL, code_list),
                          (USER_DEFINED_MISSING_VALUE_LABEL, user_defined_missing_value)]

        return metadata_files

    def validate_metadata_files(self, metadata_files):
        """
        Validate the metadata files.

        :param metadata_files: A list with tuples containing metadata file names (key, value)
        """
        for label, metadata in metadata_files:
            self.validate_file(metadata)

    def validate_file(self, file_name):
        """
        Check whether the file exists and validate the file encoding if the file exists.

        :param file_name: The physical name of the file with extension
        :return: Empty string | The physical name of the file with extension
        """
        valid_file = ''

        # Check whether the file exists.
        file_name = self.misc.is_non_empty_file(file_name)

        # Validate the file encoding
        if file_name:
            if self.misc.validate_encoding(file_name):
                # Remove byte order mark (if it exists)
                self.misc.remove_bom(file_name)
                valid_file = file_name
            else:
                self.entry_text = INVALID_ENCODING_TEXT.format(file_name)

        return valid_file

    def create_metadata_file_content(self, metadata_files):
        """
        Create the metadata file content.

        :param metadata_files: A list with tuples containing metadata file names (key, value)
        :return: A list with the metadata file content
        """
        file_content = []

        for label, metadata in metadata_files:
            # Check whether the file exists
            file = self.misc.is_non_empty_file(metadata)
            if not file:
                metadata = file

            # Add data file information
            if label == DATA_FILE_INFORMATION_LABEL:
                if metadata:
                    file_content.extend(self.add_data_file_information(metadata))
                else:
                    file_content.extend(self.add_empty_data_file_information())
                    # Update entry text
                    self.entry_text = NO_METADATA_TEXT.format(DATA_FILE_INFORMATION_LABEL)
            # Add variable list
            elif label == VARIABLE_LIST_LABEL:
                if metadata:
                    file_content.extend(self.add_variable_list(metadata))
                else:
                    file_content.extend(self.add_empty_variable_list())
                    # Update entry text
                    self.entry_text = NO_METADATA_TEXT.format(VARIABLE_LIST_LABEL)
            # Add variable description
            elif label == VARIABLE_DESCRIPTION_LABEL:
                if metadata:
                    file_content.extend(self.add_variable_description(metadata))
                else:
                    file_content.extend(self.add_empty_variable_description())
                    # Update entry text
                    self.entry_text = NO_METADATA_TEXT.format(VARIABLE_DESCRIPTION_LABEL)
            # Add code list(s)
            elif label == CODE_LIST_LABEL:
                if metadata:
                    file_content.extend(self.add_code_lists(metadata))
                else:
                    file_content.extend(self.add_empty_code_lists())
                    # Update entry text
                    self.entry_text = NO_METADATA_TEXT.format(CODE_LIST_LABEL)
            # Add user-defined missing values
            elif label == USER_DEFINED_MISSING_VALUE_LABEL:
                if metadata:
                    file_content.extend(self.add_user_defined_missing_value(metadata))
                else:
                    file_content.extend(self.add_empty_user_defined_missing_value())
                    # Update entry text
                    self.entry_text = NO_METADATA_TEXT.format(USER_DEFINED_MISSING_VALUE_LABEL)

        return file_content

    def add_data_file_information(self, metadata):
        """
        Add content from the metadata file to a list.

        :param metadata: The physical name of the metadata file with extension
        :return: A list with the metadata file content
        """
        metadata_file_content = []

        file_content = self.misc.list_comprehension(metadata)
        metadata_file_content.extend(file_content)

        return metadata_file_content

    @staticmethod
    def add_empty_data_file_information():
        """
        Add metadata labels to a list.
        """
        metadata_file_content = []

        metadata_file_content.extend([APPLICATION_NAME_LABEL, NEW_LINE])
        metadata_file_content.extend([NEW_LINE, DATA_FILE_NAME_LABEL, NEW_LINE])
        metadata_file_content.extend([NEW_LINE, DATA_FILE_DESCRIPTION_LABEL, NEW_LINE])
        metadata_file_content.extend([NEW_LINE, KEY_VARIABLE_LABEL, NEW_LINE])
        metadata_file_content.extend([NEW_LINE, DATA_FILE_REFERENCE_LABEL, NEW_LINE, NEW_LINE])

        return metadata_file_content

    def add_variable_list(self, metadata):
        """
        Add content from the metadata file to a list.

        :param metadata: The physical name of the metadata file with extension
        :return: A list with the metadata file content
        """
        metadata_file_content = []

        metadata_file_content.extend([VARIABLE_LIST_LABEL])
        metadata_file_content.extend(self.misc.list_comprehension(metadata))

        return metadata_file_content

    @staticmethod
    def add_empty_variable_list():
        """
        Add metadata labels to a list.

        :return: A list with the metadata file content
        """
        metadata_file_content = []
        metadata_file_content.extend([VARIABLE_LIST_LABEL, NEW_LINE])

        return metadata_file_content

    def add_variable_description(self, metadata):
        """
        Add content from the metadata file to a list.

        :param metadata: The physical name of the metadata file with extension
        :return: A list with the metadata file content
        """
        metadata_file_content = []

        metadata_file_content.extend([NEW_LINE, VARIABLE_DESCRIPTION_LABEL])
        metadata_file_content.extend(self.misc.list_comprehension(metadata))

        return metadata_file_content

    @staticmethod
    def add_empty_variable_description():
        """
        Add metadata labels to a list.

        :return: A list with the metadata file content
        """
        metadata_file_content = []
        metadata_file_content.extend([NEW_LINE, VARIABLE_DESCRIPTION_LABEL, NEW_LINE])

        return metadata_file_content

    def add_code_lists(self, metadata):
        """
        Add content from the metadata file to a list.

        :param metadata: The physical name of the metadata file with extension
        :return: A list with the metadata file content
        """
        metadata_file_content = []

        metadata_file_content.extend([NEW_LINE, CODE_LIST_LABEL])
        metadata_file_content.extend(self.misc.list_comprehension(metadata))

        return metadata_file_content

    @staticmethod
    def add_empty_code_lists():
        """
        Add metadata labels to a list.

        :return: A list with the metadata file content
        """
        metadata_file_content = []
        metadata_file_content.extend([NEW_LINE, CODE_LIST_LABEL, NEW_LINE])

        return metadata_file_content

    def add_user_defined_missing_value(self, metadata):
        """
        Add content from the metadata file to a list.

        :param metadata: The physical name of the metadata file with extension
        :return: A list with the metadata file content
        """
        metadata_file_content = []

        metadata_file_content.extend([NEW_LINE, USER_DEFINED_MISSING_VALUE_LABEL])
        metadata_file_content.extend(self.misc.list_comprehension(metadata))

        return metadata_file_content

    @staticmethod
    def add_empty_user_defined_missing_value():
        """
        Add metadata labels to a list.

        :return: A list with the metadata file content
        """
        metadata_file_content = []
        metadata_file_content.extend([NEW_LINE, USER_DEFINED_MISSING_VALUE_LABEL, NEW_LINE, NEW_LINE])

        return metadata_file_content

    @staticmethod
    def write_full_metadata_file(file_name, metadata_file_content):
        """
        Write a UTF-8 encoded metadata file with content from all existing metadata files.

        :param file_name: The physical name of the data file without extension
        :param metadata_file_content: A list with the metadata file content
        """
        list_content = []

        # Add line breaks
        for item in metadata_file_content:
            list_content.extend('%s\n' % item)
        # Convert list to string
        string_content = ''.join(list_content)
        # Convert string to bytes (encode)
        byte_syntax = string_content.encode(UTF8)

        # Get file name
        file = ''.join([file_name, METADATA])

        # Write syntax file
        with open(file, WRITE_MODE, encoding=UTF8) as f:
            # Convert bytes to string (decode)
            f.write(byte_syntax.decode(UTF8))

Leave a Reply

Your email address will not be published.