Skip to content

Commit

Permalink
Some extra support for unknonw language codes.
Browse files Browse the repository at this point in the history
  • Loading branch information
mihxil committed Oct 6, 2024
1 parent c16776b commit ccc4799
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 31 deletions.
18 changes: 16 additions & 2 deletions src/main/java/org/meeuw/i18n/languages/ISO_639.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@
*/
public class ISO_639 {

static ThreadLocal<Boolean> ignoreNotFound = ThreadLocal.withInitial(() -> Boolean.FALSE);

public static void setIgnoreNotFound() {
ignoreNotFound.set(Boolean.TRUE);
}

public static void removeIgnoreNotFound() {
ignoreNotFound.remove();
}

private ISO_639() {
}
/**
Expand Down Expand Up @@ -198,8 +208,12 @@ public static Optional<ISO_639_Code> get(String code) {
* @throws IllegalArgumentException if not found
*/
public static ISO_639_Code iso639(String code) {
return get(code)
.orElseThrow(() -> new IllegalArgumentException("Unknown language code '" + code + "'"));
if (ignoreNotFound.get()) {
return get(code).orElse(LanguageCode.NOTFOUND);
} else {
return get(code)
.orElseThrow(() -> new IllegalArgumentException("Unknown language code '" + code + "'"));
}
}


Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/meeuw/i18n/languages/ISO_639_3_Code.java
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ public List<NameRecord> nameRecords() {
}

@Size
public NameRecord nameRecord(Locale locale) {
public NameRecord name(Locale locale) {
if (locale.getLanguage().equals("en")) {
return names.get(0);
} else {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/meeuw/i18n/languages/ISO_639_Code.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
@XmlJavaTypeAdapter(LanguageCodeAdapter.class)
public interface ISO_639_Code extends Serializable {


/**
* The code associated with this language or language family.
*
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/org/meeuw/i18n/languages/LanguageCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/**
* A language with a ISO 639-3 language code (of three letters). Also, aware of the ISO-630-1 2-letter codes if that exists.
*<p>
* Annotated with {@link XmlJavaTypeAdapter}, so it will automatically be marshalled and unmarshalled in XML's.
* Annotated with {@link XmlJavaTypeAdapter}, so it will automatically be marshalled and unmarshalled in XMLs.
* <p>
* Also annotated with jackson annotation, to be marshalled and unmarshalled in JSON as the code.
*<p>
Expand All @@ -26,6 +26,11 @@
@XmlJavaTypeAdapter(LanguageCodeAdapter.class)
public interface LanguageCode extends ISO_639_Code {

UserDefinedLanguage UNKNOWN = new UserDefinedLanguage("UNKNOWN", null, "unknown language", "the language for some reason is unknown or unrecognized");

UserDefinedLanguage NOTFOUND = new UserDefinedLanguage("NOTFOUND", null, "language not found", "the language is not found");


/**
* A stream with all known {@link ISO_639_Code language codes}.
*
Expand Down Expand Up @@ -195,8 +200,12 @@ static Optional<LanguageCode> get(String code) {
* @throws IllegalArgumentException if not found
*/
static LanguageCode languageCode(String code) {
return get(code)
.orElseThrow(() -> new IllegalArgumentException("Unknown language code '" + code + "'"));
if (ISO_639.ignoreNotFound.get()) {
return get(code).orElse(NOTFOUND);
} else {
return get(code)
.orElseThrow(() -> new IllegalArgumentException("Unknown language code '" + code + "'"));
}
}

/**
Expand Down Expand Up @@ -351,7 +360,7 @@ default Locale toLocale() {
return new Locale(code());
}

default NameRecord nameRecord(Locale locale) {
default NameRecord name(Locale locale) {
if (locale.getLanguage().equals("en")) {
return nameRecords().get(0);
} else {
Expand Down
83 changes: 83 additions & 0 deletions src/main/java/org/meeuw/i18n/languages/UserDefinedLanguage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.meeuw.i18n.languages;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class UserDefinedLanguage implements LanguageCode {

private static final Map<String, UserDefinedLanguage> registered = new ConcurrentHashMap<>();

private final String code;
private final Type type;
private final String refName;
private final String comment;

public UserDefinedLanguage(String code, Type type, String refName, String comment) {
this.code = code;
this.type = type;
this.refName = refName;
this.comment = comment;
}


@Override
public String code() {
return code;
}

@Override
public String part3() {
return null;
}

@Override
public String part2B() {
return null;
}

@Override
public String part2T() {
return null;
}

@Override
public String part1() {
return null;
}

@Override
public Scope scope() {
return null;
}

@Override
public Type languageType() {
return type;
}

@Override
public String refName() {
return refName;
}

@Override
public String comment() {
return comment;
}

@Override
public List<NameRecord> nameRecords() {
return List.of();
}

@Override
public List<LanguageCode> macroLanguages() {
return List.of();
}

@Override
public List<LanguageCode> individualLanguages() {
return List.of();
}
}
121 changes: 97 additions & 24 deletions src/test/java/org/meeuw/i18n/languages/test/SerializationTest.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
package org.meeuw.i18n.languages.test;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.xml.bind.JAXB;
import java.io.*;
import static org.assertj.core.api.Assertions.assertThat;

import jakarta.xml.bind.JAXB;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.meeuw.i18n.languages.ISO_639_Code;
import org.meeuw.i18n.languages.*;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.ValueInstantiationException;

import static org.assertj.core.api.Assertions.assertThat;
import static org.meeuw.i18n.languages.ISO_639.iso639;
import org.meeuw.i18n.languages.LanguageCode;
import static org.meeuw.i18n.languages.LanguageCode.NOTFOUND;
import static org.meeuw.i18n.languages.LanguageCode.UNKNOWN;


public class SerializationTest {

/**
* Test serializing/deserializing to XML
*/
Expand All @@ -23,12 +33,44 @@ public void xml(String code) {
new A(iso639(code), LanguageCode.languageCode("be")), writer);
System.out.println(writer);
A a = JAXB.unmarshal(new StringReader(writer.toString()), A.class);


assertThat(a.isoCode).isSameAs(iso639(code));
}



/**
* Test deserializing from XML (erroneous)
*/
@Test
public void xmlErroneous() {
{
A a = JAXB.unmarshal(new StringReader("<a languageCode='zz' />"), A.class);

assertThat(a.languageCode).isNull();
}
try {
ISO_639.setIgnoreNotFound();
A a = JAXB.unmarshal(new StringReader("<a languageCode='zz' />"), A.class);
assertThat(a.languageCode).isEqualTo(NOTFOUND);
} finally {
ISO_639.removeIgnoreNotFound();
}

try {
ISO_639.registerFallback("zz", UNKNOWN);
A a = JAXB.unmarshal(new StringReader("<a languageCode='zz' />"), A.class);
assertThat(a.languageCode).isEqualTo(UNKNOWN);
} finally {
ISO_639.resetFallBacks();
}




}



/**
* Test serializing/deserializing to XML
*/
Expand All @@ -38,38 +80,69 @@ public void json(String code) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
String targetCode = iso639(code).code();
//objectMapper.registerModule(new org.meeuw.i18n.languages.jackson.LanguageModule(true));

String s = objectMapper.writeValueAsString(new A(iso639(code), LanguageCode.languageCode("be")));
System.out.println(s);

assertThat(s).isEqualTo("{\"isoCode\":\"" + targetCode + "\",\"languageCode\":\"be\"}");

A rounded = objectMapper.readValue(s, A.class);
assertThat(rounded.isoCode.code()).isEqualTo(targetCode);
assertThat(rounded.isoCode.code()).isEqualTo(targetCode);
}

/**
* Test deserializing from XML (erroneous)
*/
@Test
public void jsonErroneous() throws JsonProcessingException {
String code = "zz";
ObjectMapper objectMapper = new ObjectMapper();


Assertions.assertThatThrownBy(() -> {
A a = objectMapper.readValue("{\"languageCode\": \"" + code + "\"}", A.class);
}).isInstanceOf(ValueInstantiationException.class);

try {
ISO_639.setIgnoreNotFound();
A a = objectMapper.readValue("{\"languageCode\": \"" + code + "\"}", A.class);
assertThat(a.languageCode).isEqualTo(NOTFOUND);
} finally {
ISO_639.removeIgnoreNotFound();
}
try {
ISO_639.registerFallback("zz", UNKNOWN);
A a = objectMapper.readValue("{\"languageCode\": \"" + code + "\"}", A.class);
assertThat(a.languageCode).isEqualTo(UNKNOWN);
} finally {
ISO_639.resetFallBacks();
}
}









/**
* Test java serializing/deserializing
* Test java serializing/deserializing
*/
@ParameterizedTest
@ValueSource(strings = {"nld", "gem"})
public void serialize(String code) throws IOException, ClassNotFoundException {
ISO_639_Code looked = iso639(code);
A a = new A(looked, LanguageCode.languageCode("be"));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream
ObjectOutputStream objectOutputStream
= new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(a);


ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
A deserialized = (A) inputStream.readObject();
assertThat(deserialized.isoCode.code()).isEqualTo(looked.code());
assertThat(deserialized.isoCode).isSameAs(looked);



}


}

0 comments on commit ccc4799

Please sign in to comment.