def test_remove_aggregation(self):
        # test that when an instance GeoFeatureLogicalFile (aggregation) is deleted
        # all resource files associated with that aggregation is not deleted but the associated
        # metadata is deleted

        self.create_composite_resource(self.states_required_zip_file)
        res_file = self.composite_resource.files.first()
        file_folder = res_file.file_folder
        base_file_name, _ = os.path.splitext(res_file.file_name)

        # set the zip file to GeoFeatureLogicalFile (aggregation) type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)

        # test that we have one logical file (aggregation) of type GeoFeatureLogicalFile
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 1)
        logical_file = GeoFeatureLogicalFile.objects.first()
        self.assertEqual(logical_file.files.all().count(), 3)
        self.assertEqual(self.composite_resource.files.all().count(), 3)
        self.assertEqual(set(self.composite_resource.files.all()),
                         set(logical_file.files.all()))

        # delete the aggregation (logical file) object using the remove_aggregation function
        logical_file.remove_aggregation()
        # test there is no GeoFeatureLogicalFile object
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # test there is no GeoFeatureFileMetaData object
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
        # check the files associated with the aggregation not deleted
        self.assertEqual(self.composite_resource.files.all().count(), 3)
        # check the file folder is not deleted
        for f in self.composite_resource.files.all():
            self.assertEqual(f.file_folder, file_folder)
        self.composite_resource.delete()
    def test_create_aggregation_from_zip_file_required_1(self):
        # here we are using a zip file that has only the 3 required files for setting it
        # to Geo Feature file type which includes metadata extraction
        # the zip file that we are using to create an aggregation here is at the root of the
        # folder hierarchy

        self.create_composite_resource(self.states_required_zip_file)

        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()
        base_file_name, _ = os.path.splitext(res_file.file_name)
        # check that the resource file is not associated with any logical file type
        self.assertEqual(res_file.has_logical_file, False)

        res_file = self.composite_resource.files.first()
        self.assertEqual(res_file.extension, '.zip')

        # set the zip file to GeoFeatureLogicalFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)

        # test file type and file type metadata
        assert_geofeature_file_type_metadata(self, expected_folder_name='')

        # there should not be any file level keywords
        res_file = self.composite_resource.files.first()
        logical_file = res_file.logical_file
        self.assertEqual(logical_file.metadata.keywords, [])

        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GeoFeatureFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
    def test_geofeature_file_type_folder_delete(self):
        # when  a file is set to geofeaturelogical file type
        # system automatically creates a folder using the name of the file
        # that was used to set the file type
        # Here we need to test that when that folder gets deleted, all files
        # in that folder gets deleted, the logicalfile object gets deleted and
        # the associated metadata objects get deleted

        self._create_composite_resource(self.states_required_zip_file)
        res_file = self.composite_resource.files.first()

        # extract metadata from the zip file
        GeoFeatureLogicalFile.set_file_type(self.composite_resource,
                                            res_file.id, self.user)
        # test that we have one logical file of type GeoFeatureLogicalFile type as a result
        # of metadata extraction
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 1)
        # should have one GeoFeatureFileMetadata object
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 1)

        # there should be 3 content files
        self.assertEqual(self.composite_resource.files.count(), 3)
        # delete the folder for the logical file
        folder_path = "data/contents/states_required_files"
        remove_folder(self.user, self.composite_resource.short_id, folder_path)
        # there should be no content files
        self.assertEqual(self.composite_resource.files.count(), 0)
        # there should not be any logical file or file metadata object as a result
        # of folder deletion
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
        self.composite_resource.delete()
    def test_aggregation_file_move(self):
        # test any resource file that's part of the GeoFeature logical file can't be moved

        self.create_composite_resource(self.states_required_zip_file)
        res_file = self.composite_resource.files.first()
        base_file_name, _ = os.path.splitext(res_file.file_name)
        # extract metadata from the tif file
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)
        # test renaming of files that are associated with geo feature LFO - which should
        # raise exception
        self.assertEqual(self.composite_resource.files.count(), 3)
        new_folder = 'geofeature_aggr'
        ResourceFile.create_folder(self.composite_resource, new_folder)

        # moving any of the resource files to this new folder should raise exception
        tgt_path = 'data/contents/geofeature_aggr'
        for res_file in self.composite_resource.files.all():
            with self.assertRaises(DRF_ValidationError):
                src_path = os.path.join('data', 'contents',
                                        res_file.short_path)
                move_or_rename_file_or_folder(self.user,
                                              self.composite_resource.short_id,
                                              src_path, tgt_path)

        self.composite_resource.delete()
    def test_file_metadata_on_resource_delete(self):
        # test that when the composite resource is deleted
        # all metadata associated with GeoFeatureLogicalFile Type is deleted

        self.create_composite_resource(self.states_required_zip_file)
        res_file = self.composite_resource.files.first()

        # extract metadata from the tif file
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)

        # test that we have one logical file of type GeoFeatureLogicalFile as a result
        # of metadata extraction
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 1)

        # test that we have the metadata elements
        # there should be no Coverage objects
        self.assertEqual(Coverage.objects.count(), 0)
        self.assertEqual(GeometryInformation.objects.count(), 1)
        self.assertEqual(OriginalCoverage.objects.count(), 1)
        self.assertEqual(FieldInformation.objects.count(), 5)

        # delete resource
        hydroshare.delete_resource(self.composite_resource.short_id)

        # test that we have no logical file of type GeoFeatureLogicalFileType
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)

        # test that all metadata deleted
        self.assertEqual(Coverage.objects.count(), 0)
        self.assertEqual(GeometryInformation.objects.count(), 0)
        self.assertEqual(OriginalCoverage.objects.count(), 0)
        self.assertEqual(FieldInformation.objects.count(), 0)
    def test_logical_file_delete(self):
        # test that when an instance GeoFeatureLogicalFile Type is deleted
        # all files associated with GeoFeatureLogicalFile is deleted

        self.create_composite_resource(self.states_required_zip_file)
        res_file = self.composite_resource.files.first()

        # extract metadata from the tif file
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)

        # test that we have one logical file of type GeoRasterFileType as a result
        # of metadata extraction
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        logical_file = GeoFeatureLogicalFile.objects.first()
        self.assertEqual(logical_file.files.all().count(), 3)
        self.assertEqual(self.composite_resource.files.all().count(), 3)
        self.assertEqual(set(self.composite_resource.files.all()),
                         set(logical_file.files.all()))

        # delete the logical file using the custom delete function - logical_delete()
        logical_file.logical_delete(self.user)
        self.assertEqual(self.composite_resource.files.all().count(), 0)

        self.composite_resource.delete()
    def test_zip_invalid_set_file_type_to_geo_feature(self):
        # here we are using a invalid zip file that is missing the shx file
        # to set Geo Feature file type which should fail

        self.create_composite_resource(self.states_zip_invalid_file)

        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()

        # check that the resource file is not associated with any logical file
        self.assertEqual(res_file.has_logical_file, False)

        # set the tif file to GeoFeatureFile type
        with self.assertRaises(ValidationError):
            GeoFeatureLogicalFile.set_file_type(self.composite_resource,
                                                self.user, res_file.id)

        # test file was rolled back
        self.assertEqual(self.composite_resource.files.count(), 1)
        # check that there is no GeoFeatureLogicalFile object
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        res_file = self.composite_resource.files.first()

        # check that the resource file is not associated with any logical file
        self.assertEqual(res_file.has_logical_file, False)
        self.composite_resource.delete()
    def test_create_aggregation_from_shp_file_required_3(self):
        # here we are using a shp file that exists in a folder
        # for setting it to Geo Feature file type which includes metadata extraction
        # The same folder contains another file that is not going to be part of the
        # geofeature aggregation a new folder should be created in this case to represent the
        # geofeature aggregation
        # location shp file before aggregation is created: my_folder/states.shp
        # location of another file before aggregation is created: my_folder/states_invalid.zip
        # location of shp file after aggregation is created: my_folder/states/states.shp
        # location of another file after aggregation is created: my_folder/states_invalid.zip

        self.create_composite_resource()

        new_folder = 'my_folder'
        ResourceFile.create_folder(self.composite_resource, new_folder)
        # add the 3 required files to the resource at the above folder
        res_file = self.add_file_to_resource(file_to_add=self.states_shp_file,
                                             upload_folder=new_folder)
        self.assertEqual(res_file.file_folder, new_folder)
        res_file = self.add_file_to_resource(file_to_add=self.states_shx_file,
                                             upload_folder=new_folder)
        self.assertEqual(res_file.file_folder, new_folder)
        res_file = self.add_file_to_resource(file_to_add=self.states_dbf_file,
                                             upload_folder=new_folder)
        self.assertEqual(res_file.file_folder, new_folder)

        self.assertEqual(self.composite_resource.files.all().count(), 3)

        # add a file that is not related to aggregation
        res_file = self.add_file_to_resource(
            file_to_add=self.states_zip_invalid_file, upload_folder=new_folder)
        self.assertEqual(res_file.file_folder, new_folder)
        self.assertEqual(self.composite_resource.files.all().count(), 4)
        # check that the resource file is not associated with any logical file
        self.assertEqual(res_file.has_logical_file, False)
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # set the shp file to GeoFeatureLogicalFile type
        shp_res_file = [
            f for f in self.composite_resource.files.all()
            if f.extension == '.shp'
        ][0]
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            shp_res_file.id)
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        base_shp_file_base_name, _ = os.path.splitext(shp_res_file.file_name)
        shp_res_file = [
            f for f in self.composite_resource.files.all()
            if f.extension == '.shp'
        ][0]
        logical_file = shp_res_file.logical_file
        self.assertEqual(logical_file.files.count(), 3)
        for res_file in logical_file.files.all():
            # test that the each resource file has the same folder - no new folder created
            self.assertEqual(res_file.file_folder, new_folder)
        self.assertEqual(self.composite_resource.files.all().count(), 4)
        self.composite_resource.delete()
    def test_zip_set_file_type_to_geo_feature(self):
        # only do federation testing when REMOTE_USE_IRODS is True and irods docker containers
        # are set up properly
        if not super(GeoFeatureFileTypeMetaDataTest,
                     self).is_federated_irods_available():
            return

        # here we are using a valid zip file for setting it
        # to Geo Feature file type which includes metadata extraction
        fed_test_file_full_path = '/{zone}/home/{username}/{fname}'.format(
            zone=settings.HS_USER_IRODS_ZONE,
            username=self.user.username,
            fname=self.zip_file_name)
        res_upload_files = []
        fed_res_path = hydroshare.utils.get_federated_zone_home_path(
            fed_test_file_full_path)
        self.composite_resource = hydroshare.create_resource(
            resource_type='CompositeResource',
            owner=self.user,
            title='Federated Composite Resource Raster File Type Testing',
            files=res_upload_files,
            source_names=[fed_test_file_full_path],
            fed_res_path=fed_res_path,
            move=False,
            metadata=[])

        # test resource is created on federated zone
        self.assertNotEqual(self.composite_resource.resource_federation_path,
                            '')

        # set the logical file -which get sets as part of the post resource creation signal
        resource_post_create_actions(resource=self.composite_resource,
                                     user=self.user,
                                     metadata=self.composite_resource.metadata)
        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()
        expected_folder_name = res_file.file_name[:-4]
        # check that the resource file is associated with GenericLogicalFile
        self.assertEqual(res_file.has_logical_file, True)
        self.assertEqual(res_file.logical_file_type_name, "GenericLogicalFile")
        # check that there is one GenericLogicalFile object
        self.assertEqual(GenericLogicalFile.objects.count(), 1)
        fed_file_path = "{}/data/contents/{}".format(
            self.composite_resource.root_path, self.zip_file_name)
        self.assertEqual(res_file.storage_path, fed_file_path)

        # set the zip file to GeoFeatureFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource,
                                            res_file.id, self.user)
        # test file type and file type extracted metadata
        assert_geofeature_file_type_metadata(self, expected_folder_name)
        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GenericFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
    def _test_file_metadata_on_file_delete(self, ext):
        self.create_composite_resource(self.osm_all_files_zip_file)
        res_file = self.composite_resource.files.first()
        # set the zip file to GeoFeatureFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)

        # test files in the file type
        self.assertEqual(self.composite_resource.files.count(), 15)
        # check that there is no GenericLogicalFile object
        self.assertEqual(GenericLogicalFile.objects.count(), 0)
        # check that there is one GeoFeatureLogicalFile object
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        # check that there is one GeoFeatureFileMetaData
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 1)
        logical_file = GeoFeatureLogicalFile.objects.first()
        self.assertEqual(logical_file.files.count(), 15)

        # one at the file level and one at the resource level
        self.assertEqual(Coverage.objects.count(), 2)
        self.assertEqual(FieldInformation.objects.count(), 7)
        self.assertEqual(GeometryInformation.objects.count(), 1)
        self.assertEqual(OriginalCoverage.objects.count(), 1)
        res_file = self.composite_resource.files.first()
        logical_file = res_file.logical_file
        self.assertEqual(len(logical_file.metadata.keywords), 2)
        for key in ('Logan River', 'TauDEM'):
            self.assertIn(key, logical_file.metadata.keywords)

        # delete content file specified by extension (ext parameter)
        res_file = hydroshare.utils.get_resource_files_by_extension(
            self.composite_resource, ext)[0]
        hydroshare.delete_resource_file(self.composite_resource.short_id,
                                        res_file.id, self.user)
        # test that we don't have logical file of type GeoFeatureLogicalFile type
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)

        # test that all metadata got deleted - there should be still1 coverage at the resource level
        self.assertEqual(
            self.composite_resource.metadata.coverages.all().count(), 1)
        self.assertEqual(Coverage.objects.count(), 1)
        self.assertEqual(FieldInformation.objects.count(), 0)
        self.assertEqual(GeometryInformation.objects.count(), 0)
        self.assertEqual(OriginalCoverage.objects.count(), 0)

        # there should not be any files left
        self.assertEqual(self.composite_resource.files.count(), 0)
        self.composite_resource.delete()
    def test_create_aggregation_from_zip_file_required_2(self):
        # here we are using a zip file that has only the 3 required files for setting it
        # to Geo Feature file type which includes metadata extraction
        # the zip file that we are using to create an aggregation here is not at the root of the
        # folder hierarchy but in a folder - no new folder should be created as part of creating
        # this aggregation

        self.create_composite_resource()

        new_folder = 'geofeature_aggr'
        ResourceFile.create_folder(self.composite_resource, new_folder)
        # add the the zip file to the resource at the above folder
        self.add_file_to_resource(file_to_add=self.states_required_zip_file,
                                  upload_folder=new_folder)

        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()
        self.assertEqual(res_file.file_folder, new_folder)

        # check that the resource file is not associated with any logical file type
        self.assertEqual(res_file.has_logical_file, False)
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)

        res_file = self.composite_resource.files.first()
        self.assertEqual(res_file.extension, '.zip')

        # set the zip file to GeoFeatureLogicalFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)

        # test file type and file type metadata
        assert_geofeature_file_type_metadata(self, new_folder)

        for res_file in self.composite_resource.files.all():
            # test that each resource file is part of an aggregation (logical file)
            self.assertTrue(res_file.has_logical_file)
            # test that the each resource file has the same folder - no new folder was created
            self.assertEqual(res_file.file_folder, new_folder)

        # there should not be any file level keywords
        res_file = self.composite_resource.files.first()
        logical_file = res_file.logical_file
        self.assertEqual(logical_file.metadata.keywords, [])

        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GeoFeatureFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
    def test_content_file_delete(self):
        # test that when any file in GeoFeatureLogicalFile type is deleted
        # all metadata associated with GeoFeatureLogicalFile is deleted
        # test for all 15 file extensions

        for ext in GeoFeatureLogicalFile.get_allowed_storage_file_types():
            self._test_file_metadata_on_file_delete(ext=ext)
    def test_main_file(self):
        self.create_composite_resource(self.states_required_zip_file)

        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()
        # set the zip file to GeoFeatureLogicalFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)

        self.assertEqual(1, GeoFeatureLogicalFile.objects.count())
        self.assertEqual(
            ".shp",
            GeoFeatureLogicalFile.objects.first().get_main_file_type())
        self.assertEqual(
            self.states_shp_file_name,
            GeoFeatureLogicalFile.objects.first().get_main_file.file_name)
Example #14
0
    def test_zip_set_file_type_to_geo_feature(self):
        super(GeoFeatureFileTypeMetaDataTest,
              self).assert_federated_irods_available()

        # here we are using a valid zip file for setting it
        # to Geo Feature file type which includes metadata extraction
        fed_test_file_full_path = '/{zone}/home/{username}/{fname}'.format(
            zone=settings.HS_USER_IRODS_ZONE,
            username=self.user.username,
            fname=self.zip_file_name)
        res_upload_files = []
        fed_res_path = hydroshare.utils.get_federated_zone_home_path(
            fed_test_file_full_path)
        self.composite_resource = hydroshare.create_resource(
            resource_type='CompositeResource',
            owner=self.user,
            title='Federated Composite Resource Raster File Type Testing',
            files=res_upload_files,
            source_names=[fed_test_file_full_path],
            fed_res_path=fed_res_path,
            move=False,
            metadata=[])

        # test resource is created on federated zone
        self.assertNotEqual(self.composite_resource.resource_federation_path,
                            '')
        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()
        base_file_name, _ = os.path.splitext(res_file.file_name)
        expected_folder_name = base_file_name
        # check that the resource file is not associated with logical file
        self.assertEqual(res_file.has_logical_file, False)
        fed_file_path = "{}/{}".format(self.composite_resource.file_path,
                                       self.zip_file_name)
        self.assertEqual(res_file.storage_path, fed_file_path)

        # set the zip file to GeoFeatureFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)
        # test file type and file type extracted metadata
        assert_geofeature_file_type_metadata(self, expected_folder_name)
        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GenericFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
Example #15
0
    def test_bag_ingestion(self):
        from hs_core.views.utils import unzip_file

        def normalize_metadata(metadata_str):
            """Prepares metadata string to match resource id and hydroshare url of original"""
            return metadata_str\
                .replace(current_site_url(), "http://www.hydroshare.org")\
                .replace(res.short_id, "97523bdb7b174901b3fc2d89813458f1")

        # create empty resource
        res = resource.create_resource(
            'CompositeResource',
            self.user,
            'My Test Resource'
            )
        full_paths = {}

        files_to_upload = [UploadedFile(file=open('hs_core/tests/data/test_resource_metadata_files.zip', 'rb'),
                                        name="test_resource_metadata_files.zip")]
        add_resource_files(res.short_id, *files_to_upload, full_paths=full_paths)

        unzip_file(self.user, res.short_id, "data/contents/test_resource_metadata_files.zip", True,
                   overwrite=True, auto_aggregate=True, ingest_metadata=True)

        def compare_metadatas(new_metadata_str, original_metadata_file):
            original_graph = Graph()
            with open(os.path.join(self.extracted_directory, original_metadata_file), "r") as f:
                original_graph = original_graph.parse(data=f.read())
            new_graph = Graph()
            new_graph = new_graph.parse(data=normalize_metadata(new_metadata_str))

            # remove modified date, they'll never match
            subject = new_graph.value(predicate=RDF.type, object=DCTERMS.modified)
            new_graph.remove((subject, None, None))
            subject = original_graph.value(predicate=RDF.type, object=DCTERMS.modified)
            original_graph.remove((subject, None, None))

            for (new_triple, original_triple) in _squashed_graphs_triples(new_graph, original_graph):
                self.assertEquals(new_triple, original_triple, "Ingested resource metadata does not match original")

        res.refresh_from_db()
        compare_metadatas(res.metadata.get_xml(), "resourcemetadata.xml")

        compare_metadatas(res.get_logical_files(GenericLogicalFile.type_name())[0].metadata.get_xml(),
                          "test_meta.xml")
        compare_metadatas(res.get_logical_files(FileSetLogicalFile.type_name())[0].metadata.get_xml(),
                          "asdf/asdf_meta.xml")
        compare_metadatas(res.get_logical_files(GeoFeatureLogicalFile.type_name())[0].metadata.get_xml(),
                          "watersheds_meta.xml")
        compare_metadatas(res.get_logical_files(GeoRasterLogicalFile.type_name())[0].metadata.get_xml(),
                          "logan_meta.xml")
        compare_metadatas(res.get_logical_files(NetCDFLogicalFile.type_name())[0].metadata.get_xml(),
                          "SWE_time_meta.xml")
        compare_metadatas(res.get_logical_files(RefTimeseriesLogicalFile.type_name())[0].metadata.get_xml(),
                          "msf_version.refts_meta.xml")
        compare_metadatas(res.get_logical_files(TimeSeriesLogicalFile.type_name())[0].metadata.get_xml(),
                          "ODM2_Multi_Site_One_Variable_meta.xml")
    def test_zip_set_file_type_to_geo_feature(self):
        super(GeoFeatureFileTypeMetaDataTest, self).assert_federated_irods_available()

        # here we are using a valid zip file for setting it
        # to Geo Feature file type which includes metadata extraction
        fed_test_file_full_path = '/{zone}/home/{username}/{fname}'.format(
            zone=settings.HS_USER_IRODS_ZONE, username=self.user.username,
            fname=self.zip_file_name)
        res_upload_files = []
        fed_res_path = hydroshare.utils.get_federated_zone_home_path(fed_test_file_full_path)
        self.composite_resource = hydroshare.create_resource(
            resource_type='CompositeResource',
            owner=self.user,
            title='Federated Composite Resource Raster File Type Testing',
            files=res_upload_files,
            source_names=[fed_test_file_full_path],
            fed_res_path=fed_res_path,
            move=False,
            metadata=[]
        )

        # test resource is created on federated zone
        self.assertNotEqual(self.composite_resource.resource_federation_path, '')
        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()
        base_file_name, _ = os.path.splitext(res_file.file_name)
        expected_folder_name = base_file_name
        # check that the resource file is not associated with logical file
        self.assertEqual(res_file.has_logical_file, False)
        fed_file_path = "{}/{}".format(self.composite_resource.file_path, self.zip_file_name)
        self.assertEqual(res_file.storage_path, fed_file_path)

        # set the zip file to GeoFeatureFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user, res_file.id)
        # test file type and file type extracted metadata
        assert_geofeature_file_type_metadata(self, expected_folder_name)
        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GenericFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
    def test_file_rename_or_move(self):
        # test that file can't be moved or renamed for any resource file
        # that's part of the GeoFeature logical file object (LFO)

        self._create_composite_resource(self.states_required_zip_file)
        res_file = self.composite_resource.files.first()

        # extract metadata from the tif file
        GeoFeatureLogicalFile.set_file_type(self.composite_resource,
                                            res_file.id, self.user)
        # test renaming of files that are associated with raster LFO - which should raise exception
        self.assertEqual(self.composite_resource.files.count(), 3)
        res_file = self.composite_resource.files.first()
        self.assertEqual(res_file.file_folder, 'states_required_files')
        src_path = 'data/contents/states_required_files/states.shp'
        tgt_path = 'data/contents/states_required_files/states-1.shp'
        with self.assertRaises(DRF_ValidationError):
            move_or_rename_file_or_folder(self.user,
                                          self.composite_resource.short_id,
                                          src_path, tgt_path)
        src_path = 'data/contents/states_required_files/states.dbf'
        tgt_path = 'data/contents/states_required_files/states-1.dbf'
        with self.assertRaises(DRF_ValidationError):
            move_or_rename_file_or_folder(self.user,
                                          self.composite_resource.short_id,
                                          src_path, tgt_path)
        # test moving the files associated with geo raster LFO
        src_path = 'data/contents/states_required_files/states.shx'
        tgt_path = 'data/contents/states_required_files/states-1.shx'
        with self.assertRaises(DRF_ValidationError):
            move_or_rename_file_or_folder(self.user,
                                          self.composite_resource.short_id,
                                          src_path, tgt_path)
        src_path = 'data/contents/states_required_files/states.shp'
        tgt_path = 'data/contents/states_required_files-1/states.shp'
        with self.assertRaises(DRF_ValidationError):
            move_or_rename_file_or_folder(self.user,
                                          self.composite_resource.short_id,
                                          src_path, tgt_path)

        self.composite_resource.delete()
    def test_create_aggregation_from_shp_file_required_2(self):
        # here we are using a shp file that exists in a folder
        # for setting it to Geo Feature file type which includes metadata extraction
        # no new folder should be created as part o creating this aggregation

        self.create_composite_resource()

        new_folder = 'geofeature_aggr'
        ResourceFile.create_folder(self.composite_resource, new_folder)
        # add the 3 required files to the resource at the above folder
        res_file = self.add_file_to_resource(file_to_add=self.states_shp_file,
                                             upload_folder=new_folder)
        self.assertEqual(res_file.file_folder, new_folder)
        res_file = self.add_file_to_resource(file_to_add=self.states_shx_file,
                                             upload_folder=new_folder)
        self.assertEqual(res_file.file_folder, new_folder)
        res_file = self.add_file_to_resource(file_to_add=self.states_dbf_file,
                                             upload_folder=new_folder)
        self.assertEqual(res_file.file_folder, new_folder)

        self.assertEqual(self.composite_resource.files.all().count(), 3)
        res_file = self.composite_resource.files.first()

        # check that the resource file is not associated with any logical file
        self.assertEqual(res_file.has_logical_file, False)
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # set the shp file to GeoFeatureLogicalFile type
        shp_res_file = [
            f for f in self.composite_resource.files.all()
            if f.extension == '.shp'
        ][0]
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            shp_res_file.id)
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        for res_file in self.composite_resource.files.all():
            # test that each resource file is part of an aggregation (logical file)
            self.assertTrue(res_file.has_logical_file)
            # test that the each resource file has the same folder - no new folder created
            self.assertEqual(res_file.file_folder, new_folder)

        self.composite_resource.delete()
    def test_aggregation_file_rename(self):
        # test that a file can't renamed for any resource file
        # that's part of the GeoFeature logical file

        self.create_composite_resource()
        new_folder = 'my_folder'
        ResourceFile.create_folder(self.composite_resource, new_folder)
        # add the 3 required files to the resource at the above folder
        self.add_file_to_resource(file_to_add=self.states_required_zip_file,
                                  upload_folder=new_folder)
        res_file = self.composite_resource.files.first()
        base_file_name, _ = os.path.splitext(res_file.file_name)

        # create aggregation from the zip file
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)
        # test renaming of files that are associated with aggregation raises exception
        self.assertEqual(self.composite_resource.files.count(), 3)

        src_path = 'data/contents/{}/states.shp'.format(new_folder)
        tgt_path = 'data/contents/{}/states-1.shp'.format(new_folder)
        with self.assertRaises(DRF_ValidationError):
            move_or_rename_file_or_folder(self.user,
                                          self.composite_resource.short_id,
                                          src_path, tgt_path)
        src_path = 'data/contents/{}/states.dbf'.format(new_folder)
        tgt_path = 'data/contents/{}/states-1.dbf'.format(new_folder)
        with self.assertRaises(DRF_ValidationError):
            move_or_rename_file_or_folder(self.user,
                                          self.composite_resource.short_id,
                                          src_path, tgt_path)

        src_path = 'data/contents/{}/states.shx'.format(new_folder)
        tgt_path = 'data/contents/{}/states-1.shx'.format(new_folder)
        with self.assertRaises(DRF_ValidationError):
            move_or_rename_file_or_folder(self.user,
                                          self.composite_resource.short_id,
                                          src_path, tgt_path)

        self.composite_resource.delete()
    def test_zip_set_file_type_to_geo_feature_required(self):
        # here we are using a zip file that has only the 3 required files for setting it
        # to Geo Feature file type which includes metadata extraction

        self._create_composite_resource(self.states_required_zip_file)

        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()
        expected_folder_name = res_file.file_name[:-4]
        # check that the resource file is associated with GenericLogicalFile
        self.assertEqual(res_file.has_logical_file, True)
        self.assertEqual(res_file.logical_file_type_name, "GenericLogicalFile")
        # check that there is one GenericLogicalFile object
        self.assertEqual(GenericLogicalFile.objects.count(), 1)
        res_file = self.composite_resource.files.first()
        self.assertEqual(res_file.extension, '.zip')
        logical_file = res_file.logical_file
        self.assertTrue(isinstance(logical_file.metadata, GenericFileMetaData))
        self.assertTrue(isinstance(logical_file, GenericLogicalFile))
        # no keywords at this point for file
        self.assertEqual(logical_file.metadata.keywords, [])

        # set the zip file to GeoFeatureFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource,
                                            res_file.id, self.user)

        # test file type and file type metadata
        assert_geofeature_file_type_metadata(self, expected_folder_name)

        # there should not be any file level keywords
        res_file = self.composite_resource.files.first()
        logical_file = res_file.logical_file
        self.assertEqual(logical_file.metadata.keywords, [])

        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GenericFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
    def test_shp_set_file_type_to_geo_feature_required(self):
        # here we are using a shp file for setting it
        # to Geo Feature file type which includes metadata extraction

        self._create_composite_resource()

        # add the 3 required files to the resource
        files = []
        shp_temp_file = os.path.join(self.temp_dir, self.states_shp_file_name)
        shutil.copy(self.states_shp_file, shp_temp_file)

        shx_temp_file = os.path.join(self.temp_dir, self.states_shx_file_name)
        shutil.copy(self.states_shx_file, shx_temp_file)

        dbf_temp_file = os.path.join(self.temp_dir, self.states_dbf_file_name)
        shutil.copy(self.states_dbf_file, dbf_temp_file)

        files.append(
            UploadedFile(file=open(shp_temp_file, 'r'),
                         name=self.states_shp_file_name))
        files.append(
            UploadedFile(file=open(shx_temp_file, 'r'),
                         name=self.states_shx_file_name))
        files.append(
            UploadedFile(file=open(dbf_temp_file, 'r'),
                         name=self.states_dbf_file_name))
        hydroshare.utils.resource_file_add_process(self.composite_resource,
                                                   files, self.user)

        self.assertEqual(self.composite_resource.files.all().count(), 3)
        res_file = self.composite_resource.files.first()
        expected_folder_name = res_file.file_name[:-4]
        # check that the resource file is associated with GenericLogicalFile
        self.assertEqual(res_file.has_logical_file, True)
        self.assertEqual(res_file.logical_file_type_name, "GenericLogicalFile")
        # check that there is 3 GenericLogicalFile object
        self.assertEqual(GenericLogicalFile.objects.count(), 3)

        # set the shp file to GeoFeatureFile type
        shp_res_file = [
            f for f in self.composite_resource.files.all()
            if f.extension == '.shp'
        ][0]
        GeoFeatureLogicalFile.set_file_type(self.composite_resource,
                                            shp_res_file.id, self.user)

        # test files in the file type
        self.assertEqual(self.composite_resource.files.count(), 3)
        # check that there is no GenericLogicalFile object
        self.assertEqual(GenericLogicalFile.objects.count(), 0)
        # check that there is one GeoFeatureLogicalFile object
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        logical_file = GeoFeatureLogicalFile.objects.first()
        self.assertEqual(logical_file.files.count(), 3)
        # check that the 3 resource files are now associated with GeoFeatureLogicalFile
        for res_file in self.composite_resource.files.all():
            self.assertEqual(res_file.logical_file_type_name,
                             "GeoFeatureLogicalFile")
            self.assertEqual(res_file.has_logical_file, True)
            self.assertTrue(
                isinstance(res_file.logical_file, GeoFeatureLogicalFile))
        # check that we put the 3 files in a new folder
        for res_file in self.composite_resource.files.all():
            file_path, base_file_name, _ = get_resource_file_name_and_extension(
                res_file)
            expected_file_path = "{}/data/contents/{}/{}"
            res_file.file_folder = expected_folder_name
            expected_file_path = expected_file_path.format(
                self.composite_resource.root_path, expected_folder_name,
                base_file_name)
            self.assertEqual(file_path, expected_file_path)
        # test extracted raster file type metadata
        # there should not be any resource level coverage
        self.assertEqual(self.composite_resource.metadata.coverages.count(), 0)
        self.assertNotEqual(logical_file.metadata.geometryinformation, None)
        self.assertEqual(
            logical_file.metadata.geometryinformation.featureCount, 51)
        self.assertEqual(
            logical_file.metadata.geometryinformation.geometryType,
            "MULTIPOLYGON")

        self.assertNotEqual(logical_file.metadata.originalcoverage, None)
        self.assertEqual(logical_file.metadata.originalcoverage.datum,
                         'unknown')
        self.assertEqual(
            logical_file.metadata.originalcoverage.projection_name, 'unknown')
        self.assertGreater(
            len(logical_file.metadata.originalcoverage.projection_string), 0)
        self.assertEqual(logical_file.metadata.originalcoverage.unit,
                         'unknown')
        self.assertEqual(logical_file.metadata.originalcoverage.eastlimit,
                         -66.9692712587578)
        self.assertEqual(logical_file.metadata.originalcoverage.northlimit,
                         71.406235393967)
        self.assertEqual(logical_file.metadata.originalcoverage.southlimit,
                         18.921786345087)
        self.assertEqual(logical_file.metadata.originalcoverage.westlimit,
                         -178.217598362366)

        # there should not be any file level keywords
        self.assertEqual(logical_file.metadata.keywords, [])

        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GenericFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
Example #22
0
    def handle(self, *args, **options):
        logger = logging.getLogger(__name__)
        resource_counter = 0
        to_resource_type = 'CompositeResource'
        msg = "THERE ARE CURRENTLY {} GEOFEATURE RESOURCES PRIOR TO CONVERSION.".format(
            GeographicFeatureResource.objects.all().count())
        logger.info(msg)
        print(">> {}".format(msg))

        for gf_res in GeographicFeatureResource.objects.all():
            # check resource exists on irods
            istorage = gf_res.get_irods_storage()
            if not istorage.exists(gf_res.root_path):
                err_msg = "Geofeature resource not found in irods (ID: {})".format(
                    gf_res.short_id)
                logger.error(err_msg)
                print("Error:>> {}".format(err_msg))
                # skip this geofeature resource for migration
                continue

            create_gf_aggregation = False
            if gf_res.has_required_content_files() and \
                    gf_res.metadata.geometryinformation is not None:
                create_gf_aggregation = True

            if create_gf_aggregation:
                # check resource files exist on irods
                file_missing = False
                for res_file in gf_res.files.all():
                    file_path = res_file.public_path
                    if not istorage.exists(file_path):
                        err_msg = "File path not found in irods:{}".format(
                            file_path)
                        logger.error(err_msg)
                        err_msg = "Failed to convert geofeature resource (ID: {}). " \
                                  "Resource file is missing on irods"
                        err_msg = err_msg.format(gf_res.short_id)
                        print("Error:>> {}".format(err_msg))
                        file_missing = True
                        break
                if file_missing:
                    # skip this corrupt geofeature resource for migration
                    continue

            # change the resource_type
            gf_metadata_obj = gf_res.metadata
            gf_res.resource_type = to_resource_type
            gf_res.content_model = to_resource_type.lower()
            gf_res.save()
            # get the converted resource object - CompositeResource
            comp_res = gf_res.get_content_model()

            # set CoreMetaData object for the composite resource
            core_meta_obj = CoreMetaData.objects.create()
            comp_res.content_object = core_meta_obj

            # migrate geofeature resource core metadata elements to composite resource
            migrate_core_meta_elements(gf_metadata_obj, comp_res)

            # update url attribute of the metadata 'type' element
            type_element = comp_res.metadata.type
            type_element.url = '{0}/terms/{1}'.format(current_site_url(),
                                                      to_resource_type)
            type_element.save()
            if create_gf_aggregation:
                # create a Geofeature aggregation
                gf_aggr = None
                try:
                    gf_aggr = GeoFeatureLogicalFile.create(resource=comp_res)
                except Exception as ex:
                    err_msg = 'Failed to create Geofeature aggregation for resource (ID: {})'
                    err_msg = err_msg.format(gf_res.short_id)
                    err_msg = err_msg + '\n' + ex.message
                    logger.error(err_msg)
                    print("Error:>> {}".format(err_msg))

                if gf_aggr is not None:
                    # set aggregation dataset title
                    gf_aggr.dataset_name = comp_res.metadata.title.value
                    gf_aggr.save()
                    # make the res files part of the aggregation
                    for res_file in comp_res.files.all():
                        gf_aggr.add_resource_file(res_file)

                    # migrate geofeature specific metadata to aggregation
                    for fieldinfo in gf_metadata_obj.fieldinformations.all():
                        fieldinfo.content_object = gf_aggr.metadata
                        fieldinfo.save()

                    # create aggregation level coverage elements
                    for coverage in comp_res.metadata.coverages.all():
                        aggr_coverage = Coverage()
                        aggr_coverage.type = coverage.type
                        aggr_coverage._value = coverage._value
                        aggr_coverage.content_object = gf_aggr.metadata
                        aggr_coverage.save()

                    org_coverage = gf_metadata_obj.originalcoverage
                    if org_coverage:
                        org_coverage.content_object = gf_aggr.metadata
                        org_coverage.save()

                    geom_info = gf_metadata_obj.geometryinformation
                    if geom_info:
                        geom_info.content_object = gf_aggr.metadata
                        geom_info.save()

                    # create aggregation level keywords
                    keywords = [
                        sub.value for sub in comp_res.metadata.subjects.all()
                    ]
                    gf_aggr.metadata.keywords = keywords

                    # create aggregation level xml files
                    gf_aggr.create_aggregation_xml_documents()
                    msg = 'One Geofeature aggregation was created in resource (ID: {})'
                    msg = msg.format(comp_res.short_id)
                    logger.info(msg)

            comp_res.save()
            # set resource to dirty so that resource level xml files (resource map and
            # metadata xml files) will be re-generated as part of next bag download
            try:
                set_dirty_bag_flag(comp_res)
            except Exception as ex:
                err_msg = 'Failed to set bag flag dirty for the converted resource (ID: {})'
                err_msg = err_msg.format(gf_res.short_id)
                err_msg = err_msg + '\n' + ex.message
                logger.error(err_msg)
                print("Error:>> {}".format(err_msg))

            resource_counter += 1
            # delete the instance of GeographicFeatureMetaData that was part of the original
            # geofeature resource
            gf_metadata_obj.delete()
            msg = 'Geofeature resource (ID: {}) was converted to Composite Resource type'
            msg = msg.format(comp_res.short_id)
            logger.info(msg)

        msg = "{} GEOFEATURE RESOURCES WERE CONVERTED TO COMPOSITE RESOURCE.".format(
            resource_counter)
        logger.info(msg)
        print(">> {}".format(msg))
        msg = "THERE ARE CURRENTLY {} GEOFEATURE RESOURCES AFTER CONVERSION.".format(
            GeographicFeatureResource.objects.all().count())
        logger.info(msg)
        if GeographicFeatureResource.objects.all().count() > 0:
            msg = "NOT ALL GEOFEATURE RESOURCES WERE CONVERTED TO COMPOSITE RESOURCE TYPE"
            logger.error(msg)
        print(">> {}".format(msg))
    def test_aggregation_folder_move(self):
        # test changes to aggregation name, aggregation metadata xml file path, and aggregation
        # resource map xml file path on aggregation folder move

        self.create_composite_resource()
        new_folder = 'my_folder'
        ResourceFile.create_folder(self.composite_resource, new_folder)
        # add the 3 required files to the resource at the above folder
        self.add_file_to_resource(file_to_add=self.states_required_zip_file,
                                  upload_folder=new_folder)
        res_file = self.composite_resource.files.first()

        # create aggregation from the zip file
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)
        self.assertEqual(self.composite_resource.files.count(), 3)
        base_file_name, _ = os.path.splitext(res_file.file_name)
        for res_file in self.composite_resource.files.all():
            self.assertEqual(res_file.file_folder, new_folder)

        # test aggregation name
        res_file = self.composite_resource.files.first()
        logical_file = res_file.logical_file
        shp_file_path = get_path_with_no_file_extension(
            logical_file.aggregation_name)
        # test aggregation xml file paths
        expected_meta_file_path = '{0}{1}'.format(shp_file_path,
                                                  METADATA_FILE_ENDSWITH)
        self.assertEqual(logical_file.metadata_short_file_path,
                         expected_meta_file_path)

        expected_map_file_path = '{0}{1}'.format(shp_file_path,
                                                 RESMAP_FILE_ENDSWITH)
        self.assertEqual(logical_file.map_short_file_path,
                         expected_map_file_path)

        # create a folder to move the aggregation folder there
        parent_folder = 'parent_folder'
        ResourceFile.create_folder(self.composite_resource, parent_folder)
        # move the aggregation folder to the parent folder
        src_path = 'data/contents/{}'.format(new_folder)
        tgt_path = 'data/contents/{}/{}'.format(parent_folder, new_folder)

        move_or_rename_file_or_folder(self.user,
                                      self.composite_resource.short_id,
                                      src_path, tgt_path)

        file_folder = '{}/{}'.format(parent_folder, new_folder)
        for res_file in self.composite_resource.files.all():
            self.assertEqual(res_file.file_folder, file_folder)

        # test aggregation name update
        res_file = self.composite_resource.files.first()
        logical_file = res_file.logical_file
        shp_file_path = get_path_with_no_file_extension(
            logical_file.aggregation_name)

        # test aggregation xml file paths
        expected_meta_file_path = '{0}{1}'.format(shp_file_path,
                                                  METADATA_FILE_ENDSWITH)
        self.assertEqual(logical_file.metadata_short_file_path,
                         expected_meta_file_path)

        expected_map_file_path = '{0}{1}'.format(shp_file_path,
                                                 RESMAP_FILE_ENDSWITH)
        self.assertEqual(logical_file.map_short_file_path,
                         expected_map_file_path)

        self.composite_resource.delete()
Example #24
0
    def get_folder_aggregation_type_to_set(self, dir_path):
        """Returns an aggregation (file type) type that the specified folder *dir_path* can
        possibly be set to.

        :param dir_path: Resource file directory path (full folder path starting with resource id)
        for which the possible aggregation type that can be set needs to be determined

        :return If the specified folder is already represents an aggregation or does
        not contain suitable file(s) then returns "" (empty string). If the specified folder
        contains only the files that meet the requirements of a supported aggregation, and
        does not contain other folders or does not have a parent folder then return the
        class name of that matching aggregation type.
        """
        aggregation_type_to_set = ""
        if self.get_folder_aggregation_object(dir_path) is not None:
            # target folder is already an aggregation
            return None

        istorage = self.get_irods_storage()
        irods_path = dir_path
        if self.is_federated:
            irods_path = os.path.join(self.resource_federation_path,
                                      irods_path)
        store = istorage.listdir(irods_path)
        if store[0]:
            # seems there are folders under dir_path - no aggregation type can be set if the target
            # folder contains other folders
            return None

        files_in_folder = [
            res_file for res_file in self.files.all()
            if res_file.dir_path == dir_path
        ]
        if not files_in_folder:
            # folder is empty
            return None
        if len(files_in_folder) > 1:
            # check for geo feature
            aggregation_type_to_set = GeoFeatureLogicalFile.check_files_for_aggregation_type(
                files_in_folder)
            if aggregation_type_to_set:
                return aggregation_type_to_set

            # check for raster
            aggregation_type_to_set = GeoRasterLogicalFile.check_files_for_aggregation_type(
                files_in_folder)
            if aggregation_type_to_set:
                return aggregation_type_to_set
        else:
            # check for raster
            aggregation_type_to_set = GeoRasterLogicalFile.check_files_for_aggregation_type(
                files_in_folder)
            if aggregation_type_to_set:
                return aggregation_type_to_set
            # check for NetCDF aggregation type
            aggregation_type_to_set = NetCDFLogicalFile.check_files_for_aggregation_type(
                files_in_folder)
            if aggregation_type_to_set:
                return aggregation_type_to_set
            # check for TimeSeries aggregation type
            aggregation_type_to_set = TimeSeriesLogicalFile.check_files_for_aggregation_type(
                files_in_folder)
            if aggregation_type_to_set:
                return aggregation_type_to_set

        return None
    def test_create_aggregation_from_zip_file_all(self):
        # here we are using a zip file that has all the 15 files for setting it
        # to Geo Feature file type which includes metadata extraction
        # this zip file for creating aggregation is at the root of the folder hierarchy

        self.create_composite_resource(self.osm_all_files_zip_file)

        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()
        base_file_name, _ = os.path.splitext(res_file.file_name)
        # check that the resource file is not associated with any logical file type
        self.assertEqual(res_file.has_logical_file, False)

        # set the zip file to GeoFeatureLogicalFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            res_file.id)

        # test files in the file type
        self.assertEqual(self.composite_resource.files.count(), 15)
        # check that there is no GenericLogicalFile object
        self.assertEqual(GenericLogicalFile.objects.count(), 0)
        # check that there is no GenericFileMetaData object
        self.assertEqual(GenericFileMetaData.objects.count(), 0)
        # check that there is one GeoFeatureLogicalFile object
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        logical_file = GeoFeatureLogicalFile.objects.first()
        self.assertEqual(logical_file.files.count(), 15)
        # check that the 3 resource files are now associated with GeoFeatureLogicalFile
        for res_file in self.composite_resource.files.all():
            self.assertEqual(res_file.logical_file_type_name,
                             "GeoFeatureLogicalFile")
            self.assertEqual(res_file.has_logical_file, True)
            self.assertTrue(
                isinstance(res_file.logical_file, GeoFeatureLogicalFile))

        # test extracted raster file type metadata
        # there should one resource level coverage
        self.assertEqual(self.composite_resource.metadata.coverages.count(), 1)
        self.assertEqual(logical_file.metadata.fieldinformations.all().count(),
                         7)
        self.assertEqual(
            logical_file.metadata.geometryinformation.featureCount, 87)
        self.assertEqual(
            logical_file.metadata.geometryinformation.geometryType, "POLYGON")
        self.assertEqual(logical_file.metadata.originalcoverage.datum,
                         'WGS_1984')
        self.assertTrue(
            abs(logical_file.metadata.originalcoverage.eastlimit -
                3.4520493) < self.allowance)
        self.assertTrue(
            abs(logical_file.metadata.originalcoverage.northlimit -
                45.0466382) < self.allowance)
        self.assertTrue(
            abs(logical_file.metadata.originalcoverage.southlimit -
                42.5732416) < self.allowance)
        self.assertTrue(
            abs(logical_file.metadata.originalcoverage.westlimit -
                (-0.3263017)) < self.allowance)
        self.assertEqual(logical_file.metadata.originalcoverage.unit, 'degree')
        self.assertEqual(
            logical_file.metadata.originalcoverage.projection_name, 'WGS 84')

        # there should be file level keywords
        for key in ('Logan River', 'TauDEM'):
            self.assertIn(key, logical_file.metadata.keywords)
        self.assertEqual(len(logical_file.metadata.keywords), 2)

        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GenericFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
    def test_create_aggregation_from_shp_file_required_1(self):
        # here we are using a shp file that exists at the root of the folder hierarchy
        # for setting it to Geo Feature file type which includes metadata extraction

        self.create_composite_resource()

        # add the 3 required files to the resource at the above folder
        res_file = self.add_file_to_resource(file_to_add=self.states_shp_file)
        self.assertEqual(res_file.file_folder, '')
        res_file = self.add_file_to_resource(file_to_add=self.states_shx_file)
        self.assertEqual(res_file.file_folder, '')
        res_file = self.add_file_to_resource(file_to_add=self.states_dbf_file)
        self.assertEqual(res_file.file_folder, '')

        self.assertEqual(self.composite_resource.files.all().count(), 3)
        res_file = self.composite_resource.files.first()
        base_file_name, _ = os.path.splitext(res_file.file_name)
        # check that the resource file is not associated with any logical file
        self.assertEqual(res_file.has_logical_file, False)

        # set the shp file to GeoFeatureLogicalFile type
        shp_res_file = [
            f for f in self.composite_resource.files.all()
            if f.extension == '.shp'
        ][0]
        GeoFeatureLogicalFile.set_file_type(self.composite_resource, self.user,
                                            shp_res_file.id)

        # test files in the file type
        self.assertEqual(self.composite_resource.files.count(), 3)
        # check that there is no GenericLogicalFile object
        self.assertEqual(GenericLogicalFile.objects.count(), 0)
        # check that there is one GeoFeatureLogicalFile object
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        logical_file = GeoFeatureLogicalFile.objects.first()
        self.assertEqual(logical_file.files.count(), 3)
        # check that the 3 resource files are now associated with GeoFeatureLogicalFile
        for res_file in self.composite_resource.files.all():
            self.assertEqual(res_file.logical_file_type_name,
                             "GeoFeatureLogicalFile")
            self.assertEqual(res_file.has_logical_file, True)
            self.assertTrue(
                isinstance(res_file.logical_file, GeoFeatureLogicalFile))

        # test extracted raster file type metadata
        # there should not be any resource level coverage
        self.assertEqual(self.composite_resource.metadata.coverages.count(), 0)
        self.assertNotEqual(logical_file.metadata.geometryinformation, None)
        self.assertEqual(
            logical_file.metadata.geometryinformation.featureCount, 51)
        self.assertEqual(
            logical_file.metadata.geometryinformation.geometryType,
            "MULTIPOLYGON")

        self.assertNotEqual(logical_file.metadata.originalcoverage, None)
        self.assertEqual(logical_file.metadata.originalcoverage.datum,
                         'unknown')
        self.assertEqual(
            logical_file.metadata.originalcoverage.projection_name, 'unknown')
        self.assertGreater(
            len(logical_file.metadata.originalcoverage.projection_string), 0)
        self.assertEqual(logical_file.metadata.originalcoverage.unit,
                         'unknown')
        self.assertEqual(logical_file.metadata.originalcoverage.eastlimit,
                         -66.9692712587578)
        self.assertEqual(logical_file.metadata.originalcoverage.northlimit,
                         71.406235393967)
        self.assertEqual(logical_file.metadata.originalcoverage.southlimit,
                         18.921786345087)
        self.assertEqual(logical_file.metadata.originalcoverage.westlimit,
                         -178.217598362366)

        # there should not be any file level keywords
        self.assertEqual(logical_file.metadata.keywords, [])

        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GenericFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)
    def test_zip_set_file_type_to_geo_feature_all(self):
        # here we are using a zip file that has all the 15 files for setting it
        # to Geo Feature file type which includes metadata extraction

        self._create_composite_resource(self.osm_all_files_zip_file)

        self.assertEqual(self.composite_resource.files.all().count(), 1)
        res_file = self.composite_resource.files.first()
        expected_folder_name = res_file.file_name[:-4]
        # check that the resource file is associated with GenericLogicalFile
        self.assertEqual(res_file.has_logical_file, True)
        self.assertEqual(res_file.logical_file_type_name, "GenericLogicalFile")
        # check that there is one GenericLogicalFile object
        self.assertEqual(GenericLogicalFile.objects.count(), 1)

        # set the zip file to GeoFeatureFile type
        GeoFeatureLogicalFile.set_file_type(self.composite_resource,
                                            res_file.id, self.user)

        # test files in the file type
        self.assertEqual(self.composite_resource.files.count(), 15)
        # check that there is no GenericLogicalFile object
        self.assertEqual(GenericLogicalFile.objects.count(), 0)
        # check that there is no GenericFileMetaData object
        self.assertEqual(GenericFileMetaData.objects.count(), 0)
        # check that there is one GeoFeatureLogicalFile object
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 1)
        logical_file = GeoFeatureLogicalFile.objects.first()
        self.assertEqual(logical_file.files.count(), 15)
        # check that the 3 resource files are now associated with GeoFeatureLogicalFile
        for res_file in self.composite_resource.files.all():
            self.assertEqual(res_file.logical_file_type_name,
                             "GeoFeatureLogicalFile")
            self.assertEqual(res_file.has_logical_file, True)
            self.assertTrue(
                isinstance(res_file.logical_file, GeoFeatureLogicalFile))
        # check that we put the 3 files in a new folder
        for res_file in self.composite_resource.files.all():
            file_path, base_file_name, _ = get_resource_file_name_and_extension(
                res_file)
            expected_file_path = "{}/data/contents/{}/{}"
            res_file.file_folder = expected_folder_name
            expected_file_path = expected_file_path.format(
                self.composite_resource.root_path, expected_folder_name,
                base_file_name)
            self.assertEqual(file_path, expected_file_path)
        # test extracted raster file type metadata
        # there should one resource level coverage
        self.assertEqual(self.composite_resource.metadata.coverages.count(), 1)
        self.assertEqual(logical_file.metadata.fieldinformations.all().count(),
                         7)
        self.assertEqual(
            logical_file.metadata.geometryinformation.featureCount, 87)
        self.assertEqual(
            logical_file.metadata.geometryinformation.geometryType, "POLYGON")
        self.assertEqual(logical_file.metadata.originalcoverage.datum,
                         'WGS_1984')
        self.assertTrue(
            abs(logical_file.metadata.originalcoverage.eastlimit -
                3.4520493) < self.allowance)
        self.assertTrue(
            abs(logical_file.metadata.originalcoverage.northlimit -
                45.0466382) < self.allowance)
        self.assertTrue(
            abs(logical_file.metadata.originalcoverage.southlimit -
                42.5732416) < self.allowance)
        self.assertTrue(
            abs(logical_file.metadata.originalcoverage.westlimit -
                (-0.3263017)) < self.allowance)
        self.assertEqual(logical_file.metadata.originalcoverage.unit, 'Degree')
        self.assertEqual(
            logical_file.metadata.originalcoverage.projection_name,
            'GCS_WGS_1984')

        # there should be file level keywords
        for key in ('Logan River', 'TauDEM'):
            self.assertIn(key, logical_file.metadata.keywords)
        self.assertEqual(len(logical_file.metadata.keywords), 2)

        self.composite_resource.delete()
        # there should be no GeoFeatureLogicalFile object at this point
        self.assertEqual(GeoFeatureLogicalFile.objects.count(), 0)
        # there should be no GenericFileMetaData object at this point
        self.assertEqual(GeoFeatureFileMetaData.objects.count(), 0)