Skip to content

Commit

Permalink
Merge pull request #129 from UKGovLD/18-language-select
Browse files Browse the repository at this point in the history
Language selection UI
  • Loading branch information
simonoakesepimorphics authored Dec 1, 2020
2 parents 39a273b + 2c73936 commit cd009f3
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 82 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
<jena.version>3.9.0</jena.version>
<fuseki.version>3.9.0</fuseki.version>
<tomcat.version>7.0.99</tomcat.version>
<lib.version>3.1.1-SNAPSHOT</lib.version>
</properties>

<dependencies>
Expand All @@ -108,6 +109,12 @@
<!-- <version>2.1.1-SNAPSHOT</version> -->
<version>${appbase.version}</version>
</dependency>

<dependency>
<groupId>com.epimorphics</groupId>
<artifactId>lib</artifactId>
<version>${lib.version}</version>
</dependency>

<dependency>
<groupId>org.apache.jena</groupId>
Expand Down
78 changes: 43 additions & 35 deletions src/main/java/com/epimorphics/registry/core/Registry.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,46 +21,15 @@

package com.epimorphics.registry.core;

import static com.epimorphics.registry.core.Status.LIFECYCLE_REGISTER;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;

import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.util.FileUtils;
import org.apache.jena.vocabulary.RDF;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.glassfish.jersey.uri.UriComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.epimorphics.appbase.core.App;
import com.epimorphics.appbase.core.ComponentBase;
import com.epimorphics.appbase.core.GenericConfig;
import com.epimorphics.appbase.core.Shutdown;
import com.epimorphics.appbase.core.Startup;
import com.epimorphics.appbase.core.*;
import com.epimorphics.appbase.templates.VelocityRender;
import com.epimorphics.appbase.webapi.WebApiException;
import com.epimorphics.rdfutil.ModelWrapper;
import com.epimorphics.registry.core.Command.Operation;
import com.epimorphics.registry.core.ForwardingRecord.Type;
import com.epimorphics.registry.message.LocalMessagingService;
import com.epimorphics.registry.message.Message;
import com.epimorphics.registry.message.MessagingService;
import com.epimorphics.registry.message.ProcessIfChanges;
import com.epimorphics.registry.message.RequestLogger;
import com.epimorphics.registry.language.LanguageManager;
import com.epimorphics.registry.message.*;
import com.epimorphics.registry.security.UserInfo;
import com.epimorphics.registry.security.UserStore;
import com.epimorphics.registry.store.BackupService;
Expand All @@ -72,6 +41,29 @@
import com.epimorphics.registry.webapi.facets.FacetService;
import com.epimorphics.util.EpiException;
import com.epimorphics.util.FileUtil;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.util.FileUtils;
import org.apache.jena.vocabulary.RDF;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.glassfish.jersey.uri.UriComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.epimorphics.registry.core.Status.LIFECYCLE_REGISTER;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;

/**
* This the primary configuration point for the Registry.
Expand Down Expand Up @@ -125,6 +117,7 @@ public class Registry extends ComponentBase implements Startup, Shutdown {
protected GenericConfig configExtensions;
protected RequestLogger requestLogger;
protected boolean cacheRegisters = false;
protected LanguageManager languageManager = new LanguageManager.Default();

public void setBaseUri(String uri) {
baseURI = uri;
Expand Down Expand Up @@ -224,6 +217,14 @@ public void setCacheRegisters(boolean cacheRegisters) {
this.cacheRegisters = cacheRegisters;
}

public void setLanguageManager(LanguageManager languageManager) {
this.languageManager = languageManager;
}

public LanguageManager getLanguageManager() {
return languageManager;
}

@Override
public void startup(App app) {
super.startup(app);
Expand All @@ -238,7 +239,14 @@ public void startup(App app) {
registry = this; // Assumes singleton registry

// Initialize the registry RDF store from the bootstrap registers if needed
Description root = store.getDescription(getBaseURI() + "/");
Description root;
store.beginSafeRead();
try {
root = store.getDescription(getBaseURI() + "/");
} finally {
store.endSafeRead();
}

if (root == null) {
// Blank store, need to install a bootstrap root registers
for(String bootSrc : bootFile.split("\\|")) {
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/com/epimorphics/registry/language/Language.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.epimorphics.registry.language;

/**
* Representation of a supported language.
*/
interface Language {
/**
* @return The ISO 639-1 language code.
*/
String getCode();

/**
* @return The user friendly label, in the corresponding language (if available).
*/
String getLabel();

class Base implements Language {
private final String code;
private final String label;

Base(String code, String label) {
this.code = code;
this.label = label;
}

@Override public String getCode() { return code; }
@Override public String getLabel() { return label; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.epimorphics.registry.language;

import java.util.List;

/**
* Maintains the state of the registry's supported languages.
*/
interface LanguageConfig {
/**
* @return The list of languages supported by the registry.
*/
List<Language> getLanguages();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.epimorphics.registry.language;

import java.util.Collections;
import java.util.List;

/**
* Multilingual registry support.
*/
public interface LanguageManager {
/**
* Determine whether the registry is configured to support multiple languages.
* @return True if and only if multiple languages are supported.
*/
Boolean isMultilingual();

/**
* @return All of the supported languages.
*/
List<Language> getLanguages();

/**
* Determines whether to use cookies to store users' language preference.
* @return True if and only if cookies should be used. Otherwise, false.
*/
Boolean getUseCookies();

class Default implements LanguageManager {
@Override public Boolean isMultilingual() { return false; }
@Override public List<Language> getLanguages() { return Collections.emptyList(); }
@Override public Boolean getUseCookies() { return false; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package com.epimorphics.registry.language;

import com.epimorphics.appbase.core.App;
import com.epimorphics.appbase.core.Startup;
import com.epimorphics.registry.core.Description;
import com.epimorphics.registry.core.Register;
import com.epimorphics.registry.core.Registry;
import com.epimorphics.registry.message.MessagingService;
import com.epimorphics.registry.message.ProcessIfChanges;
import com.epimorphics.registry.store.RegisterEntryInfo;
import com.epimorphics.registry.store.StoreAPI;
import com.epimorphics.registry.vocab.RegistryVocab;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.rdf.model.Statement;
import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.RDFS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

public class LanguageRegister implements LanguageConfig, Startup {
private static final String REGISTER = "/system/language";

private Logger log = LoggerFactory.getLogger(LanguageRegister.class);
private List<Language> languages = new ArrayList<>();

@Override public void startup(App app) {
Registry reg = app.getA(Registry.class);
initLanguages(reg);

String register = reg.getBaseURI() + REGISTER;
MessagingService msgSvc = reg.getMessagingService();
MessagingService.Process onMonitorChange = new ProcessIfChanges(msg -> initLanguages(reg), register);

msgSvc.processMessages(onMonitorChange);
}

public synchronized void initLanguages(Registry reg) {
List<Language> nextLanguages = new ArrayList<>();

String uri = reg.getBaseURI() + REGISTER;
StoreAPI store = reg.getStore();
store.beginSafeRead();

try {
Description desc = store.getDescription(uri);
if (desc instanceof Register) {
Register register = desc.asRegister();
List<RegisterEntryInfo> members = register.getMembers();
members.forEach(entry -> addLanguage(entry, store, nextLanguages));
this.languages = nextLanguages;
} else {
log.warn("System register " + uri + " does not exist - unable to configure languages.");
}
} finally {
store.endSafeRead();
}
}

private void addLanguage(RegisterEntryInfo entry, StoreAPI store, List<Language> languages) {
Resource root = store.getDescription(entry.getEntityURI()).getRoot();
if (root.hasProperty(RDF.type, RegistryVocab.Language)) {
Statement langStmt = root.getProperty(RegistryVocab.languageCode);
if (langStmt != null) {
String lang = langStmt.getObject().asLiteral().getLexicalForm();
String label = getLabel(root, lang);
languages.add(new Language.Base(lang, label));
log.info("Registered language: " + label + " (" + lang + ")");
} else {
log.warn("Unable to add language entry " + entry.getItemURI() + ": Resource must specify a dbo:languageCode value.");
}
} else {
log.warn("Unable to add language entry " + entry.getItemURI() + ": Resource must have a rdf:type value of dbo:Language.");
}

}

private String getLabel(Resource root, String lang) {
Statement nativeLabel = root.getProperty(RDFS.label, lang);
if (nativeLabel != null) {
return nativeLabel.getObject().asLiteral().getLexicalForm();
}

Statement anyLabel = root.getProperty(RDFS.label);
if (anyLabel != null) {
return anyLabel.getObject().asLiteral().getLexicalForm();
}

return lang;
}

public List<Language> getLanguages() {
return languages;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.epimorphics.registry.language;

import java.util.List;

public class MultiLanguageManager implements LanguageManager {
private Boolean useCookies = false;
private LanguageConfig config;

public void setUseCookies(Boolean useCookies) {
this.useCookies = useCookies;
}

public void setConfig(LanguageConfig config) {
this.config = config;
}

public Boolean isMultilingual() {
return getLanguages().size() > 1;
}

public List<Language> getLanguages() {
return config.getLanguages();
}

public Boolean getUseCookies() {
return useCookies;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ public class RegistryVocab {
* of type is available.</p>
*/
public static final ObjectProperty itemClass = m_model.createObjectProperty( "http://purl.org/linked-data/registry#itemClass" );

public static final ObjectProperty languageCode = m_model.createObjectProperty("http://dbpedia.org/ontology/languageCode");

/** <p>The manager of the register, may be a person (foaf:Person) or an organization
* (org:Organization). Operates the register on behalf of the owner, makes day
Expand Down Expand Up @@ -203,6 +205,8 @@ public class RegistryVocab {
* which traverse the register hierarchy such as entity search will also be forwarded</p>
*/
public static final OntClass FederatedRegister = m_model.createClass( "http://purl.org/linked-data/registry#FederatedRegister" );

public static final OntClass Language = m_model.createClass("http://dbpedia.org/ontology/Language");

/** <p>A registerable entity which simply forwards all requests to the delegation
* target.</p>
Expand Down
Loading

0 comments on commit cd009f3

Please sign in to comment.