"""TrackArtistLocalizedMetadata Model.""" from oto import response from sqlalchemy import Column from sqlalchemy import ForeignKey from sqlalchemy import Integer from sqlalchemy import String from sqlalchemy.orm import contains_eager, relationship from product.connectors import mysql from product.constants import error from product.models.track_artist import TrackArtist class TrackArtistLocalizedMetadata(mysql.BaseModel): """Track's Artist localization Model. Represents track_artist_localized_metadata table in art_relations. """ __tablename__ = 'track_artist_localized_metadata' metadata_id = Column('id', Integer, primary_key=True, autoincrement=True) track_artist_id = Column(ForeignKey( 'track_artist.id', ondelete='CASCADE')) language_id = Column(Integer) artist_name = Column(String(255)) track_artist = relationship(TrackArtist) def to_dict(self): """Return a dictionary of a TrackArtistLocalized properties.""" response_dict = { 'language_id': self.language_id, 'track_artist_id': self.track_artist_id, 'artist_name': self.artist_name, 'tuid': None } if self.track_artist: # will only be when loaded with Join. response_dict['tuid'] = self.track_artist.tuid return response_dict def get_metadata_by_id(tuids, session): """Get track artist's localized metadata by tuids. Args: tuids (list): list of track artist ids. Returns: response.Response: a list of TrackArtistLocalizedMetadata obj or error. """ metadata = session.query(TrackArtistLocalizedMetadata) \ .join(TrackArtistLocalizedMetadata.track_artist) \ .options(contains_eager( TrackArtistLocalizedMetadata.track_artist)) \ .filter(TrackArtist.tuid.in_(tuids))\ .all() response_data = [each.to_dict() for each in metadata] return _format_artist_results(response_data) def get_artist_ids(tuids, language_id): """Get track artist ids. only the ones which has localized metadata for this tuids and language. Args: tuids (list): list of track artist ids. language_id (int): id of language. Returns: response.Response: a list of track_artist ids. """ with mysql.db_session() as session: metadata = session.query(TrackArtistLocalizedMetadata.track_artist_id)\ .join(TrackArtistLocalizedMetadata.track_artist, aliased=True) \ .filter(TrackArtist.tuid.in_(tuids))\ .filter(TrackArtistLocalizedMetadata.language_id == language_id)\ .all() response_data = [each.track_artist_id for each in metadata] return response.Response(message=response_data) def _format_artist_results(artist_metadata): """Format GET response data for legacy call with artist translations. This groups all artist metadata based on tuid and language_id. Args: artist_metadata (list): track artist metadata list. Returns: Response: dict {language : {tuid1 : {artist_id1 : trans name,}, tuid2 : {artist_id2 : trans name,}}} """ result = {} for artist in artist_metadata: language_id = artist['language_id'] tuid = artist['tuid'] if language_id not in result: result[language_id] = {} if tuid not in result[language_id]: result[language_id][tuid] = {} result[language_id][tuid].update({ artist['track_artist_id']: artist['artist_name']}) return response.Response(message=result) @mysql.db_session_wrap def update_metadata(language_id, data, session): """Add new artist localized metadata for the given track & language. Args: language_id (int): id of language. data (dict): dict containing artist localized data. e.g; {artist_id : artist_name, artist_id2 : artist_name2, ..} session (object): db session object, to make it transactional. Returns: response.Response: response object containing status and payload. """ if not isinstance(data, dict): return response.create_error_response( error.ERROR_CODE_INVALID_DATA, 'Invalid data sent for save track artist localization.') if data == {}: return response.Response(message=data) for track_artist_id, artist_name in data.items(): # update existing instead of creating new saved_artist = session.query(TrackArtistLocalizedMetadata) \ .filter_by( track_artist_id=track_artist_id, language_id=language_id)\ .one_or_none() if not saved_artist: saved_artist = TrackArtistLocalizedMetadata( track_artist_id=track_artist_id, language_id=language_id) saved_artist.artist_name = artist_name session.merge(saved_artist) return response.Response(message=data) @mysql.db_session_wrap def delete_all_metadata(track_artist_ids, session, language_id=None): """Delete artist localized metadata for the given artist_ids & language. Args: track_artist_ids (list): List of artist ids session (object): db session object, to make it transactional. language_id (int): id of language. Optional parameter. Returns: response.Response: response object. """ if not isinstance(track_artist_ids, list): return response.create_error_response( error.ERROR_CODE_INVALID_DATA, 'No artist ids sent for delete track artist localization.') delete_query = session.query(TrackArtistLocalizedMetadata) \ .filter(TrackArtistLocalizedMetadata.track_artist_id.in_( track_artist_ids)) if language_id: delete_query = delete_query.filter( TrackArtistLocalizedMetadata.language_id == language_id) records_deleted = delete_query.delete(synchronize_session=False) return response.Response( message='{} artist localizations deleted.'.format(records_deleted)) @mysql.db_session_wrap def synchronize_artist_localizations(language_id, tuids, data, session): """Synchronize existing data in DB with what is passed in data. Existing artist_ids are updated, new ids are instead and ids in db but not in data are deleted, for this language_id. Args: language_id (int): id of language. Optional parameter. tuids (list): List of track ids data (dict): new artist data. Eg: {artist_id: 'name', artist_id2:'name' ...} session (object): db session object, to make it transactional. Returns: response.Response: response object. """ artist_response = update_metadata( language_id=language_id, data=data, session=session) if not artist_response: session.rollback() return artist_response artists_with_metadata = get_artist_ids(tuids, language_id) to_delete_artist_ids = [artist for artist in artists_with_metadata.message if str(artist) not in data] if not to_delete_artist_ids: return artist_response # delete all other artists for this language+tuids that did not have data # sent in POST. delete_response = delete_all_metadata( track_artist_ids=to_delete_artist_ids, language_id=language_id, session=session) if not delete_response: session.rollback() return delete_response return artist_response