2019-01-17 18:54:05 -05:00
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
2016-11-23 15:48:37 -05:00
# include "Serialization/JsonInternationalizationArchiveSerializer.h"
# include "Misc/FileHelper.h"
# include "Serialization/JsonReader.h"
# include "Serialization/JsonSerializer.h"
# include "Serialization/JsonInternationalizationMetadataSerializer.h"
2016-08-09 11:28:56 -04:00
# include "LocTextHelper.h"
2014-09-25 18:03:04 -04:00
2014-03-14 14:13:41 -04:00
DEFINE_LOG_CATEGORY_STATIC ( LogInternationalizationArchiveSerializer , Log , All ) ;
2014-09-25 18:03:04 -04:00
const FString FJsonInternationalizationArchiveSerializer : : TAG_FORMATVERSION = TEXT ( " FormatVersion " ) ;
const FString FJsonInternationalizationArchiveSerializer : : TAG_NAMESPACE = TEXT ( " Namespace " ) ;
2016-08-09 11:28:56 -04:00
const FString FJsonInternationalizationArchiveSerializer : : TAG_KEY = TEXT ( " Key " ) ;
2014-09-25 18:03:04 -04:00
const FString FJsonInternationalizationArchiveSerializer : : TAG_CHILDREN = TEXT ( " Children " ) ;
const FString FJsonInternationalizationArchiveSerializer : : TAG_SUBNAMESPACES = TEXT ( " Subnamespaces " ) ;
const FString FJsonInternationalizationArchiveSerializer : : TAG_DEPRECATED_DEFAULTTEXT = TEXT ( " DefaultText " ) ;
const FString FJsonInternationalizationArchiveSerializer : : TAG_DEPRECATED_TRANSLATEDTEXT = TEXT ( " TranslatedText " ) ;
const FString FJsonInternationalizationArchiveSerializer : : TAG_OPTIONAL = TEXT ( " Optional " ) ;
const FString FJsonInternationalizationArchiveSerializer : : TAG_SOURCE = TEXT ( " Source " ) ;
const FString FJsonInternationalizationArchiveSerializer : : TAG_SOURCE_TEXT = TEXT ( " Text " ) ;
const FString FJsonInternationalizationArchiveSerializer : : TAG_TRANSLATION = TEXT ( " Translation " ) ;
const FString FJsonInternationalizationArchiveSerializer : : TAG_TRANSLATION_TEXT = FJsonInternationalizationArchiveSerializer : : TAG_SOURCE_TEXT ;
2016-08-09 11:28:56 -04:00
const FString FJsonInternationalizationArchiveSerializer : : TAG_METADATA = TEXT ( " MetaData " ) ;
2014-09-25 18:03:04 -04:00
const FString FJsonInternationalizationArchiveSerializer : : TAG_METADATA_KEY = TEXT ( " Key " ) ;
const FString FJsonInternationalizationArchiveSerializer : : NAMESPACE_DELIMITER = TEXT ( " . " ) ;
2014-03-14 14:13:41 -04:00
struct FCompareArchiveEntryBySourceAndKey
{
FORCEINLINE bool operator ( ) ( TSharedPtr < FArchiveEntry > A , TSharedPtr < FArchiveEntry > B ) const
{
bool bResult = false ;
if ( A - > Source < B - > Source )
{
bResult = true ;
}
else if ( A - > Source = = B - > Source )
{
if ( A - > KeyMetadataObj . IsValid ( ) ! = B - > KeyMetadataObj . IsValid ( ) )
{
bResult = B - > KeyMetadataObj . IsValid ( ) ;
}
else if ( A - > KeyMetadataObj . IsValid ( ) & & B - > KeyMetadataObj . IsValid ( ) )
{
bResult = ( * ( A - > KeyMetadataObj ) < * ( B - > KeyMetadataObj ) ) ;
}
}
return bResult ;
}
} ;
2014-09-25 18:03:04 -04:00
2014-03-14 14:13:41 -04:00
struct FCompareStructuredArchiveEntryByNamespace
{
FORCEINLINE bool operator ( ) ( TSharedPtr < FStructuredArchiveEntry > A , TSharedPtr < FStructuredArchiveEntry > B ) const
{
return A - > Namespace < B - > Namespace ;
}
} ;
2016-08-09 11:28:56 -04:00
bool FJsonInternationalizationArchiveSerializer : : DeserializeArchive ( const FString & InStr , TSharedRef < FInternationalizationArchive > InArchive , TSharedPtr < const FInternationalizationManifest > InManifest , TSharedPtr < const FInternationalizationArchive > InNativeArchive )
2014-03-14 14:13:41 -04:00
{
TSharedPtr < FJsonObject > JsonArchiveObj ;
2016-08-09 11:28:56 -04:00
TSharedRef < TJsonReader < > > Reader = TJsonReaderFactory < > : : Create ( InStr ) ;
if ( FJsonSerializer : : Deserialize ( Reader , JsonArchiveObj ) & & JsonArchiveObj . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
return DeserializeInternal ( JsonArchiveObj . ToSharedRef ( ) , InArchive , InManifest , InNativeArchive ) ;
2014-03-14 14:13:41 -04:00
}
2016-08-09 11:28:56 -04:00
return false ;
2014-03-14 14:13:41 -04:00
}
2014-09-25 18:03:04 -04:00
2016-08-09 11:28:56 -04:00
bool FJsonInternationalizationArchiveSerializer : : DeserializeArchive ( TSharedRef < FJsonObject > InJsonObj , TSharedRef < FInternationalizationArchive > InArchive , TSharedPtr < const FInternationalizationManifest > InManifest , TSharedPtr < const FInternationalizationArchive > InNativeArchive )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
return DeserializeInternal ( InJsonObj , InArchive , InManifest , InNativeArchive ) ;
2014-03-14 14:13:41 -04:00
}
2014-09-25 18:03:04 -04:00
2016-08-09 11:28:56 -04:00
bool FJsonInternationalizationArchiveSerializer : : DeserializeArchiveFromFile ( const FString & InJsonFile , TSharedRef < FInternationalizationArchive > InArchive , TSharedPtr < const FInternationalizationManifest > InManifest , TSharedPtr < const FInternationalizationArchive > InNativeArchive )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
// Read in file as string
FString FileContents ;
if ( ! FFileHelper : : LoadFileToString ( FileContents , * InJsonFile ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
UE_LOG ( LogInternationalizationArchiveSerializer , Error , TEXT ( " Failed to load archive '%s'. " ) , * InJsonFile ) ;
return false ;
2014-03-14 14:13:41 -04:00
}
2016-08-09 11:28:56 -04:00
// Parse as JSON
TSharedPtr < FJsonObject > JsonObject ;
TSharedRef < TJsonReader < > > JsonReader = TJsonReaderFactory < > : : Create ( FileContents ) ;
if ( ! FJsonSerializer : : Deserialize ( JsonReader , JsonObject ) | | ! JsonObject . IsValid ( ) )
{
UE_LOG ( LogInternationalizationArchiveSerializer , Error , TEXT ( " Failed to parse archive '%s'. %s. " ) , * InJsonFile , * JsonReader - > GetErrorMessage ( ) ) ;
return false ;
}
return DeserializeInternal ( JsonObject . ToSharedRef ( ) , InArchive , InManifest , InNativeArchive ) ;
2014-03-14 14:13:41 -04:00
}
2014-09-25 18:03:04 -04:00
2016-08-09 11:28:56 -04:00
bool FJsonInternationalizationArchiveSerializer : : SerializeArchive ( TSharedRef < const FInternationalizationArchive > InArchive , FString & Str )
2014-03-14 14:13:41 -04:00
{
TSharedRef < FJsonObject > JsonArchiveObj = MakeShareable ( new FJsonObject ) ;
2016-08-09 11:28:56 -04:00
bool bExecSuccessful = SerializeInternal ( InArchive , JsonArchiveObj ) ;
2014-03-14 14:13:41 -04:00
if ( bExecSuccessful )
{
TSharedRef < TJsonWriter < > > Writer = TJsonWriterFactory < > : : Create ( & Str ) ;
bExecSuccessful = FJsonSerializer : : Serialize ( JsonArchiveObj , Writer ) ;
Writer - > Close ( ) ;
}
2016-08-09 11:28:56 -04:00
2014-03-14 14:13:41 -04:00
return bExecSuccessful ;
}
2014-09-25 18:03:04 -04:00
2016-08-09 11:28:56 -04:00
bool FJsonInternationalizationArchiveSerializer : : SerializeArchive ( TSharedRef < const FInternationalizationArchive > InArchive , TSharedRef < FJsonObject > InJsonObj )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
return SerializeInternal ( InArchive , InJsonObj ) ;
2014-03-14 14:13:41 -04:00
}
2014-09-25 18:03:04 -04:00
2016-08-09 11:28:56 -04:00
bool FJsonInternationalizationArchiveSerializer : : SerializeArchiveToFile ( TSharedRef < const FInternationalizationArchive > InArchive , const FString & InJsonFile )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
TSharedRef < FJsonObject > JsonObject = MakeShareable ( new FJsonObject ( ) ) ;
if ( ! SerializeArchive ( InArchive , JsonObject ) )
2014-09-14 19:37:14 -04:00
{
2016-08-09 11:28:56 -04:00
UE_LOG ( LogInternationalizationArchiveSerializer , Error , TEXT ( " Failed to serialize archive '%s'. " ) , * InJsonFile ) ;
return false ;
}
// Print the JSON data to a string
FString OutputJsonString ;
TSharedRef < TJsonWriter < > > JsonWriter = TJsonWriterFactory < > : : Create ( & OutputJsonString ) ;
FJsonSerializer : : Serialize ( JsonObject , JsonWriter ) ;
// Save the JSON string (force Unicode for our manifest and archive files)
if ( ! FFileHelper : : SaveStringToFile ( OutputJsonString , * InJsonFile , FFileHelper : : EEncodingOptions : : ForceUnicode ) )
{
UE_LOG ( LogInternationalizationArchiveSerializer , Error , TEXT ( " Failed to save archive '%s'. " ) , * InJsonFile ) ;
return false ;
}
return true ;
}
bool FJsonInternationalizationArchiveSerializer : : DeserializeInternal ( TSharedRef < FJsonObject > InJsonObj , TSharedRef < FInternationalizationArchive > InArchive , TSharedPtr < const FInternationalizationManifest > InManifest , TSharedPtr < const FInternationalizationArchive > InNativeArchive )
{
if ( InJsonObj - > HasField ( TAG_FORMATVERSION ) )
{
const int32 FormatVersion = static_cast < int32 > ( InJsonObj - > GetNumberField ( TAG_FORMATVERSION ) ) ;
2016-09-21 10:07:18 -04:00
if ( FormatVersion > ( int32 ) FInternationalizationArchive : : EFormatVersion : : Latest )
{
// Archive is too new to be loaded!
return false ;
}
2016-08-09 11:28:56 -04:00
InArchive - > SetFormatVersion ( static_cast < FInternationalizationArchive : : EFormatVersion > ( FormatVersion ) ) ;
2014-09-14 19:37:14 -04:00
}
else
{
2016-08-09 11:28:56 -04:00
InArchive - > SetFormatVersion ( FInternationalizationArchive : : EFormatVersion : : Initial ) ;
2014-09-14 19:37:14 -04:00
}
2016-08-09 11:28:56 -04:00
if ( InArchive - > GetFormatVersion ( ) < FInternationalizationArchive : : EFormatVersion : : AddedKeys & & ! InManifest . IsValid ( ) )
{
// Cannot load these archives without a manifest to key against
return false ;
}
if ( JsonObjToArchive ( InJsonObj , FString ( ) , InArchive , InManifest , InNativeArchive ) )
{
// We've been upgraded to the latest format now...
InArchive - > SetFormatVersion ( FInternationalizationArchive : : EFormatVersion : : Latest ) ;
return true ;
}
return false ;
2014-03-14 14:13:41 -04:00
}
2014-09-25 18:03:04 -04:00
2016-08-09 11:28:56 -04:00
bool FJsonInternationalizationArchiveSerializer : : SerializeInternal ( TSharedRef < const FInternationalizationArchive > InArchive , TSharedRef < FJsonObject > JsonObj )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
TSharedPtr < FStructuredArchiveEntry > RootElement = MakeShareable ( new FStructuredArchiveEntry ( FString ( ) ) ) ;
2014-03-14 14:13:41 -04:00
// Condition the data so that it exists in a structured hierarchy for easy population of the JSON object.
2016-08-09 11:28:56 -04:00
GenerateStructuredData ( InArchive , RootElement ) ;
2014-03-14 14:13:41 -04:00
2016-08-09 11:28:56 -04:00
SortStructuredData ( RootElement ) ;
2014-03-14 14:13:41 -04:00
// Clear anything that may be in the JSON object
JsonObj - > Values . Empty ( ) ;
2014-09-14 19:37:14 -04:00
// Set format version.
2016-08-09 11:28:56 -04:00
JsonObj - > SetNumberField ( TAG_FORMATVERSION , static_cast < double > ( InArchive - > GetFormatVersion ( ) ) ) ;
2014-09-14 19:37:14 -04:00
2014-03-14 14:13:41 -04:00
// Setup the JSON object using the structured data created
2016-08-09 11:28:56 -04:00
StructuredDataToJsonObj ( RootElement , JsonObj ) ;
2014-03-14 14:13:41 -04:00
return true ;
}
2014-09-25 18:03:04 -04:00
2016-08-09 11:28:56 -04:00
bool FJsonInternationalizationArchiveSerializer : : JsonObjToArchive ( TSharedRef < FJsonObject > InJsonObj , const FString & ParentNamespace , TSharedRef < FInternationalizationArchive > InArchive , TSharedPtr < const FInternationalizationManifest > InManifest , TSharedPtr < const FInternationalizationArchive > InNativeArchive )
2014-03-14 14:13:41 -04:00
{
bool bConvertSuccess = true ;
FString AccumulatedNamespace = ParentNamespace ;
2016-08-09 11:28:56 -04:00
if ( InJsonObj - > HasField ( TAG_NAMESPACE ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
if ( ! ( AccumulatedNamespace . IsEmpty ( ) ) )
2014-03-14 14:13:41 -04:00
{
AccumulatedNamespace + = NAMESPACE_DELIMITER ;
}
2016-08-09 11:28:56 -04:00
AccumulatedNamespace + = InJsonObj - > GetStringField ( TAG_NAMESPACE ) ;
2014-03-14 14:13:41 -04:00
}
else
{
2016-08-09 11:28:56 -04:00
UE_LOG ( LogInternationalizationArchiveSerializer , Warning , TEXT ( " Encountered an object with a missing namespace while converting to Internationalization archive. " ) ) ;
2014-03-14 14:13:41 -04:00
bConvertSuccess = false ;
}
// Process all the child objects
2016-08-09 11:28:56 -04:00
if ( bConvertSuccess & & InJsonObj - > HasField ( TAG_CHILDREN ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
const TArray < TSharedPtr < FJsonValue > > ChildrenArray = InJsonObj - > GetArrayField ( TAG_CHILDREN ) ;
2014-03-14 14:13:41 -04:00
2016-08-09 11:28:56 -04:00
for ( TArray < TSharedPtr < FJsonValue > > : : TConstIterator ChildIter ( ChildrenArray . CreateConstIterator ( ) ) ; ChildIter ; + + ChildIter )
2014-03-14 14:13:41 -04:00
{
const TSharedPtr < FJsonValue > ChildEntry = * ChildIter ;
const TSharedPtr < FJsonObject > ChildJSONObject = ChildEntry - > AsObject ( ) ;
FString SourceText ;
TSharedPtr < FLocMetadataObject > SourceMetadata ;
2016-08-09 11:28:56 -04:00
if ( ChildJSONObject - > HasTypedField < EJson : : String > ( TAG_DEPRECATED_DEFAULTTEXT ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
SourceText = ChildJSONObject - > GetStringField ( TAG_DEPRECATED_DEFAULTTEXT ) ;
}
else if ( ChildJSONObject - > HasTypedField < EJson : : Object > ( TAG_SOURCE ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
const TSharedPtr < FJsonObject > SourceJSONObject = ChildJSONObject - > GetObjectField ( TAG_SOURCE ) ;
if ( SourceJSONObject - > HasTypedField < EJson : : String > ( TAG_SOURCE_TEXT ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
SourceText = SourceJSONObject - > GetStringField ( TAG_SOURCE_TEXT ) ;
2014-03-14 14:13:41 -04:00
// Source meta data is mixed in with the source text, we'll process metadata if the source json object has more than one entry
2016-08-09 11:28:56 -04:00
if ( SourceJSONObject - > Values . Num ( ) > 1 )
2014-03-14 14:13:41 -04:00
{
// We load in the entire source object as metadata and just remove the source text.
2016-08-09 11:28:56 -04:00
FJsonInternationalizationMetaDataSerializer : : DeserializeMetadata ( SourceJSONObject . ToSharedRef ( ) , SourceMetadata ) ;
if ( SourceMetadata . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
SourceMetadata - > Values . Remove ( TAG_SOURCE_TEXT ) ;
2014-03-14 14:13:41 -04:00
}
}
}
else
{
bConvertSuccess = false ;
}
}
else
{
bConvertSuccess = false ;
}
FString TranslationText ;
TSharedPtr < FLocMetadataObject > TranslationMetadata ;
2016-08-09 11:28:56 -04:00
if ( ChildJSONObject - > HasTypedField < EJson : : String > ( TAG_DEPRECATED_TRANSLATEDTEXT ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
TranslationText = ChildJSONObject - > GetStringField ( TAG_DEPRECATED_TRANSLATEDTEXT ) ;
}
else if ( ChildJSONObject - > HasTypedField < EJson : : Object > ( TAG_TRANSLATION ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
const TSharedPtr < FJsonObject > TranslationJSONObject = ChildJSONObject - > GetObjectField ( TAG_TRANSLATION ) ;
if ( TranslationJSONObject - > HasTypedField < EJson : : String > ( TAG_TRANSLATION_TEXT ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
TranslationText = TranslationJSONObject - > GetStringField ( TAG_TRANSLATION_TEXT ) ;
2014-03-14 14:13:41 -04:00
// Source meta data is mixed in with the source text, we'll process metadata if the source json object has more than one entry
2016-08-09 11:28:56 -04:00
if ( TranslationJSONObject - > Values . Num ( ) > 1 )
2014-03-14 14:13:41 -04:00
{
// We load in the entire source object as metadata and remove the source text
2016-08-09 11:28:56 -04:00
FJsonInternationalizationMetaDataSerializer : : DeserializeMetadata ( TranslationJSONObject . ToSharedRef ( ) , TranslationMetadata ) ;
if ( TranslationJSONObject . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
TranslationJSONObject - > Values . Remove ( TAG_TRANSLATION_TEXT ) ;
2014-03-14 14:13:41 -04:00
}
}
}
else
{
bConvertSuccess = false ;
}
}
else
{
bConvertSuccess = false ;
}
2016-08-09 11:28:56 -04:00
if ( bConvertSuccess )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
FLocItem Source ( SourceText ) ;
2014-03-14 14:13:41 -04:00
Source . MetadataObj = SourceMetadata ;
2016-08-09 11:28:56 -04:00
FLocItem Translation ( TranslationText ) ;
2014-03-14 14:13:41 -04:00
Translation . MetadataObj = TranslationMetadata ;
bool bIsOptional = false ;
2016-08-09 11:28:56 -04:00
if ( ChildJSONObject - > HasTypedField < EJson : : Boolean > ( TAG_OPTIONAL ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
bIsOptional = ChildJSONObject - > GetBoolField ( TAG_OPTIONAL ) ;
2014-03-14 14:13:41 -04:00
}
2018-02-22 11:25:06 -05:00
TArray < FLocKey > Keys ;
2016-08-09 11:28:56 -04:00
TSharedPtr < FLocMetadataObject > KeyMetadataNode ;
if ( InArchive - > GetFormatVersion ( ) < FInternationalizationArchive : : EFormatVersion : : AddedKeys )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
// We used to store the key meta-data as a top-level value, rather than within a "MetaData" object
if ( ChildJSONObject - > HasTypedField < EJson : : Object > ( TAG_METADATA_KEY ) )
{
const TSharedPtr < FJsonObject > MetaDataKeyJSONObject = ChildJSONObject - > GetObjectField ( TAG_METADATA_KEY ) ;
FJsonInternationalizationMetaDataSerializer : : DeserializeMetadata ( MetaDataKeyJSONObject . ToSharedRef ( ) , KeyMetadataNode ) ;
}
if ( InManifest . IsValid ( ) )
{
// We have no key in the archive data, so we must try and infer it from the manifest
FLocTextHelper : : FindKeysForLegacyTranslation ( InManifest . ToSharedRef ( ) , InNativeArchive , AccumulatedNamespace , SourceText , KeyMetadataNode , Keys ) ;
}
}
else
{
if ( ChildJSONObject - > HasTypedField < EJson : : String > ( TAG_KEY ) )
{
Keys . Add ( ChildJSONObject - > GetStringField ( TAG_KEY ) ) ;
}
if ( ChildJSONObject - > HasTypedField < EJson : : Object > ( TAG_METADATA ) )
{
const TSharedPtr < FJsonObject > MetaDataJSONObject = ChildJSONObject - > GetObjectField ( TAG_METADATA ) ;
if ( MetaDataJSONObject - > HasTypedField < EJson : : Object > ( TAG_METADATA_KEY ) )
{
const TSharedPtr < FJsonObject > MetaDataKeyJSONObject = MetaDataJSONObject - > GetObjectField ( TAG_METADATA_KEY ) ;
FJsonInternationalizationMetaDataSerializer : : DeserializeMetadata ( MetaDataKeyJSONObject . ToSharedRef ( ) , KeyMetadataNode ) ;
}
}
2014-03-14 14:13:41 -04:00
}
2018-02-22 11:25:06 -05:00
for ( const FLocKey & Key : Keys )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
const bool bAddSuccessful = InArchive - > AddEntry ( AccumulatedNamespace , Key , Source , Translation , KeyMetadataNode , bIsOptional ) ;
if ( ! bAddSuccessful )
{
2018-02-22 11:25:06 -05:00
UE_LOG ( LogInternationalizationArchiveSerializer , Warning , TEXT ( " Could not add JSON entry to the Internationalization archive: Namespace:%s Key:%s DefaultText:%s " ) , * AccumulatedNamespace , * Key . GetString ( ) , * SourceText ) ;
2016-08-09 11:28:56 -04:00
}
2014-03-14 14:13:41 -04:00
}
}
}
}
2016-08-09 11:28:56 -04:00
if ( bConvertSuccess & & InJsonObj - > HasField ( TAG_SUBNAMESPACES ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
const TArray < TSharedPtr < FJsonValue > > SubnamespaceArray = InJsonObj - > GetArrayField ( TAG_SUBNAMESPACES ) ;
2014-03-14 14:13:41 -04:00
2016-08-09 11:28:56 -04:00
for ( TArray < TSharedPtr < FJsonValue > > : : TConstIterator SubnamespaceIter ( SubnamespaceArray . CreateConstIterator ( ) ) ; SubnamespaceIter ; + + SubnamespaceIter )
2014-03-14 14:13:41 -04:00
{
const TSharedPtr < FJsonValue > SubnamespaceEntry = * SubnamespaceIter ;
const TSharedPtr < FJsonObject > SubnamespaceJSONObject = SubnamespaceEntry - > AsObject ( ) ;
2016-08-09 11:28:56 -04:00
if ( ! JsonObjToArchive ( SubnamespaceJSONObject . ToSharedRef ( ) , AccumulatedNamespace , InArchive , InManifest , InNativeArchive ) )
2014-03-14 14:13:41 -04:00
{
bConvertSuccess = false ;
break ;
}
}
}
return bConvertSuccess ;
}
2016-08-09 11:28:56 -04:00
void FJsonInternationalizationArchiveSerializer : : GenerateStructuredData ( TSharedRef < const FInternationalizationArchive > InArchive , TSharedPtr < FStructuredArchiveEntry > RootElement )
2014-03-14 14:13:41 -04:00
{
//Loop through all the unstructured archive entries and build up our structured hierarchy
2016-08-09 11:28:56 -04:00
for ( FArchiveEntryByStringContainer : : TConstIterator It ( InArchive - > GetEntriesBySourceTextIterator ( ) ) ; It ; + + It )
2014-03-14 14:13:41 -04:00
{
const TSharedRef < FArchiveEntry > UnstructuredArchiveEntry = It . Value ( ) ;
TArray < FString > NamespaceTokens ;
// Tokenize the namespace by using '.' as a delimiter
2018-02-22 11:25:06 -05:00
int32 NamespaceTokenCount = UnstructuredArchiveEntry - > Namespace . GetString ( ) . ParseIntoArray ( NamespaceTokens , * NAMESPACE_DELIMITER , true ) ;
2014-03-14 14:13:41 -04:00
TSharedPtr < FStructuredArchiveEntry > StructuredArchiveEntry = RootElement ;
//Loop through all the namespace tokens and find the appropriate structured entry, if it does not exist add it. At the end StructuredArchiveEntry
// will point to the correct hierarchy entry for a given namespace
for ( int32 TokenIndex = 0 ; TokenIndex < NamespaceTokenCount ; + + TokenIndex )
{
TSharedPtr < FStructuredArchiveEntry > FoundNamespaceEntry ;
for ( int SubNamespaceIndex = 0 ; SubNamespaceIndex < StructuredArchiveEntry - > SubNamespaces . Num ( ) ; SubNamespaceIndex + + )
{
2017-03-10 15:37:02 -05:00
if ( StructuredArchiveEntry - > SubNamespaces [ SubNamespaceIndex ] - > Namespace . Equals ( NamespaceTokens [ TokenIndex ] , ESearchCase : : CaseSensitive ) )
2014-03-14 14:13:41 -04:00
{
FoundNamespaceEntry = StructuredArchiveEntry - > SubNamespaces [ SubNamespaceIndex ] ;
break ;
}
}
if ( ! FoundNamespaceEntry . IsValid ( ) )
{
int32 index = StructuredArchiveEntry - > SubNamespaces . Add ( MakeShareable ( new FStructuredArchiveEntry ( NamespaceTokens [ TokenIndex ] ) ) ) ;
FoundNamespaceEntry = StructuredArchiveEntry - > SubNamespaces [ index ] ;
}
StructuredArchiveEntry = FoundNamespaceEntry ;
}
// We add the unstructured Archive entry to the hierarchy
StructuredArchiveEntry - > ArchiveEntries . AddUnique ( UnstructuredArchiveEntry ) ;
}
}
2014-09-25 18:03:04 -04:00
void FJsonInternationalizationArchiveSerializer : : SortStructuredData ( TSharedPtr < FStructuredArchiveEntry > InElement )
2014-03-14 14:13:41 -04:00
{
if ( ! InElement . IsValid ( ) )
{
return ;
}
// Sort the manifest entries by source text.
InElement - > ArchiveEntries . Sort ( FCompareArchiveEntryBySourceAndKey ( ) ) ;
// Sort the subnamespaces by namespace string
InElement - > SubNamespaces . Sort ( FCompareStructuredArchiveEntryByNamespace ( ) ) ;
// Do the sorting for each of the subnamespaces
for ( TArray < TSharedPtr < FStructuredArchiveEntry > > : : TIterator Iter ( InElement - > SubNamespaces . CreateIterator ( ) ) ; Iter ; + + Iter )
{
TSharedPtr < FStructuredArchiveEntry > SubElement = * Iter ;
SortStructuredData ( SubElement ) ;
}
}
2014-09-25 18:03:04 -04:00
void FJsonInternationalizationArchiveSerializer : : StructuredDataToJsonObj ( TSharedPtr < const FStructuredArchiveEntry > InElement , TSharedRef < FJsonObject > OutJsonObj )
2014-03-14 14:13:41 -04:00
{
OutJsonObj - > SetStringField ( TAG_NAMESPACE , InElement - > Namespace ) ;
TArray < TSharedPtr < FJsonValue > > NamespaceArray ;
TArray < TSharedPtr < FJsonValue > > EntryArray ;
//Write namespace content entries
for ( TArray < TSharedPtr < FArchiveEntry > > : : TConstIterator Iter ( InElement - > ArchiveEntries ) ; Iter ; + + Iter )
{
const TSharedPtr < FArchiveEntry > Entry = * Iter ;
TSharedPtr < FJsonObject > EntryNode = MakeShareable ( new FJsonObject ) ;
2014-09-14 19:37:14 -04:00
FString ProcessedSourceText = Entry - > Source . Text ;
FString ProcessedTranslation = Entry - > Translation . Text ;
2014-03-14 14:13:41 -04:00
TSharedPtr < FJsonObject > SourceNode ;
if ( Entry - > Source . MetadataObj . IsValid ( ) )
{
2014-09-25 18:03:04 -04:00
FJsonInternationalizationMetaDataSerializer : : SerializeMetadata ( Entry - > Source . MetadataObj . ToSharedRef ( ) , SourceNode ) ;
2014-03-14 14:13:41 -04:00
}
if ( ! SourceNode . IsValid ( ) )
{
SourceNode = MakeShareable ( new FJsonObject ) ;
}
SourceNode - > SetStringField ( TAG_SOURCE_TEXT , ProcessedSourceText ) ;
EntryNode - > SetObjectField ( TAG_SOURCE , SourceNode ) ;
TSharedPtr < FJsonObject > TranslationNode ;
if ( Entry - > Translation . MetadataObj . IsValid ( ) )
{
2014-09-25 18:03:04 -04:00
FJsonInternationalizationMetaDataSerializer : : SerializeMetadata ( Entry - > Translation . MetadataObj . ToSharedRef ( ) , TranslationNode ) ;
2014-03-14 14:13:41 -04:00
}
if ( ! TranslationNode . IsValid ( ) )
{
TranslationNode = MakeShareable ( new FJsonObject ) ;
}
TranslationNode - > SetStringField ( TAG_TRANSLATION_TEXT , ProcessedTranslation ) ;
EntryNode - > SetObjectField ( TAG_TRANSLATION , TranslationNode ) ;
2018-02-22 11:25:06 -05:00
EntryNode - > SetStringField ( TAG_KEY , Entry - > Key . GetString ( ) ) ;
2016-08-09 11:28:56 -04:00
2014-03-14 14:13:41 -04:00
if ( Entry - > KeyMetadataObj . IsValid ( ) )
{
2016-08-09 11:28:56 -04:00
TSharedRef < FJsonObject > MetaDataNode = MakeShareable ( new FJsonObject ( ) ) ;
EntryNode - > SetObjectField ( TAG_METADATA , MetaDataNode ) ;
TSharedPtr < FJsonObject > KeyMetaDataNode ;
FJsonInternationalizationMetaDataSerializer : : SerializeMetadata ( Entry - > KeyMetadataObj . ToSharedRef ( ) , KeyMetaDataNode ) ;
if ( KeyMetaDataNode . IsValid ( ) )
2014-03-14 14:13:41 -04:00
{
2016-08-09 11:28:56 -04:00
MetaDataNode - > SetObjectField ( TAG_METADATA_KEY , KeyMetaDataNode ) ;
2014-03-14 14:13:41 -04:00
}
}
// We only add the optional field if it is true, it is assumed to be false otherwise.
if ( Entry - > bIsOptional = = true )
{
EntryNode - > SetBoolField ( TAG_OPTIONAL , Entry - > bIsOptional ) ;
}
EntryArray . Add ( MakeShareable ( new FJsonValueObject ( EntryNode ) ) ) ;
}
//Write the subnamespaces
for ( TArray < TSharedPtr < FStructuredArchiveEntry > > : : TConstIterator Iter ( InElement - > SubNamespaces ) ; Iter ; + + Iter )
{
const TSharedPtr < FStructuredArchiveEntry > SubElement = * Iter ;
if ( SubElement . IsValid ( ) )
{
TSharedRef < FJsonObject > SubObject = MakeShareable ( new FJsonObject ) ;
StructuredDataToJsonObj ( SubElement , SubObject ) ;
NamespaceArray . Add ( MakeShareable ( new FJsonValueObject ( SubObject ) ) ) ;
}
}
if ( EntryArray . Num ( ) > 0 )
{
OutJsonObj - > SetArrayField ( TAG_CHILDREN , EntryArray ) ;
}
if ( NamespaceArray . Num ( ) > 0 )
{
OutJsonObj - > SetArrayField ( TAG_SUBNAMESPACES , NamespaceArray ) ;
}
}