Skip to content

Commit

Permalink
Merge pull request #18 from epsilonlabs/13-add-preferred-language-set…
Browse files Browse the repository at this point in the history
…ting-to-limit-the-literals-being-returned

#13 add preferred language setting to limit the literals being returned
  • Loading branch information
agarciadom authored Dec 20, 2024
2 parents 5f18345 + e982871 commit f05488b
Show file tree
Hide file tree
Showing 18 changed files with 477 additions and 33 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,16 @@ spider.`name_literal@ru`.println('Name literal of Spiderman in Russian: ');
* `value`: the raw value of the literal (usually a String, but it can be different for typed literals - see [Apache Jena typed literals](https://jena.apache.org/documentation/notes/typed-literals.html)).
* `language`: the language tag for the literal (if any).
* `datatypeURI`: the datatype URI for the literal.

### Limiting returned literals to preferred languages

The "Language tag preference" section of the RDF model configuration dialog allows for specifying a comma-separated list of [BCP 47](https://www.ietf.org/rfc/bcp/bcp47.txt) language tags.
If these preferences are set, `x.property` will filter literals, by only returning the values for the first tag with matches, or falling back to the untagged values if no matches are found for any of the mentioned tags.

For instance, if we set the language preferences to `en-gb,en`, filtering `x.property` will work as follows:

* If any `en-gb` literals exist, return only those.
* If any `en` literals exist, return only those.
* Otherwise, return the untagged literals (if any).

Language preferences do not apply if an explicit language tag is used: `x.property@en` will always get the `en`-tagged literals, and `x.property@` will always get the untagged literals.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.core.resources.IFile;
Expand All @@ -33,13 +35,17 @@
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

public class RDFModelConfigurationDialog extends AbstractModelConfigurationDialog {

Expand Down Expand Up @@ -74,7 +80,7 @@ protected Object getValue(Object element) {
protected void setValue(Object element, Object value) {
((NamespaceMappingTableEntry)element).prefix = String.valueOf(value);
viewer.update(element, null);
validateURLs();
validateForm();
}
}

Expand Down Expand Up @@ -107,7 +113,7 @@ protected Object getValue(Object element) {
protected void setValue(Object element, Object value) {
((NamespaceMappingTableEntry)element).url = String.valueOf(value);
viewer.update(element, null);
validateURLs();
validateForm();
}
}

Expand Down Expand Up @@ -140,7 +146,7 @@ protected Object getValue(Object element) {
protected void setValue(Object element, Object value) {
((URLTableEntry)element).url = String.valueOf(value);
viewer.update(element, null);
validateURLs();
validateForm();
}
}

Expand Down Expand Up @@ -177,6 +183,7 @@ protected void createGroups(Composite control) {
createNameAliasGroup(control);
createRDFUrlsGroup(control);
createNamespaceMappingGroup(control);
createLanguagePreferenceGroup(control);
}

private Composite createNamespaceMappingGroup(Composite parent) {
Expand Down Expand Up @@ -346,6 +353,7 @@ public void widgetSelected(SelectionEvent e) {
urls.remove(it.next());
}
urlList.refresh();
validateForm();
}
}
});
Expand All @@ -357,6 +365,7 @@ public void widgetSelected(SelectionEvent e) {
public void widgetSelected(SelectionEvent e) {
urls.clear();
urlList.refresh();
validateForm();
}
});

Expand All @@ -365,6 +374,30 @@ public void widgetSelected(SelectionEvent e) {
return groupContent;
}


protected Label languagePreferenceLabel;
protected Text languagePreferenceText;

private Composite createLanguagePreferenceGroup(Composite parent) {
final Composite groupContent = DialogUtil.createGroupContainer(parent, "Language tag preference", 1);

languagePreferenceLabel = new Label(groupContent, SWT.NONE);
languagePreferenceLabel.setText("Comma-separated preferred language tags, in descending priority:");

languagePreferenceText = new Text(groupContent, SWT.BORDER);
languagePreferenceText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
languagePreferenceText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent event) {
validateForm();
}
});

groupContent.layout();
groupContent.pack();
return groupContent;
}

@Override
protected void loadProperties(){
super.loadProperties();
Expand All @@ -389,12 +422,14 @@ protected void loadProperties(){
}
}
}

languagePreferenceText.setText(properties.getProperty(RDFModel.PROPERTY_LANGUAGE_PREFERENCE));

this.urlList.refresh();
this.nsMappingTable.refresh();
validateURLs();
validateForm();
}

@Override
protected void storeProperties(){
super.storeProperties();
Expand All @@ -408,9 +443,27 @@ protected void storeProperties(){
String.join(",", nsMappingEntries.stream()
.map(e -> e.prefix + "=" + e.url)
.collect(Collectors.toList())));

properties.put(RDFModel.PROPERTY_LANGUAGE_PREFERENCE,
languagePreferenceText.getText().replaceAll("\\s", ""));
}

protected void validateURLs() {
protected void validateForm() {
String text = languagePreferenceText.getText().strip();
if (text.length() > 0) {
Set<String> invalidTags = new HashSet<>();
for (String tag : text.split(",")) {
if (!RDFModel.isValidLanguageTag(tag)) {
invalidTags.add(tag);
}
}
if (!invalidTags.isEmpty()) {
setErrorMessage(String.format(
"Invalid tags: %s", String.join(" ", invalidTags)));
return;
}
}

for (URLTableEntry entry : this.urls) {
String errorMessage = validateURL(entry.url);
if (errorMessage != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

Expand All @@ -38,6 +39,8 @@

public class RDFModel extends CachedModel<RDFModelElement> {

public static final String PROPERTY_LANGUAGE_PREFERENCE = "languagePreference";

public static final String PROPERTY_URIS = "uris";

/**
Expand All @@ -50,6 +53,7 @@ public class RDFModel extends CachedModel<RDFModelElement> {
*/
public static final String PROPERTY_PREFIXES = "prefixes";

protected final List<String> languagePreference = new ArrayList<>();
protected final Map<String, String> customPrefixesMap = new HashMap<>();
protected final List<String> uris = new ArrayList<>();
protected Model model;
Expand Down Expand Up @@ -136,13 +140,16 @@ public void load(StringProperties properties, IRelativePathResolver resolver) th
* EMC drivers (e.g. the EmfModel class).
*/
this.uris.clear();
for (String uri : properties.getProperty(PROPERTY_URIS).split(",")) {
this.uris.add(uri.strip());
String sUris = properties.getProperty(PROPERTY_URIS, "").strip();
if (!sUris.isEmpty()) {
for (String uri : sUris.split(",")) {
this.uris.add(uri.strip());
}
}

this.customPrefixesMap.clear();
String sPrefixes = properties.getProperty(PROPERTY_PREFIXES, "").strip();
if (sPrefixes.length() > 0) {
if (!sPrefixes.isEmpty()) {
for (String sItem : sPrefixes.split(",")) {
int idxEquals = sItem.indexOf('=');
if (idxEquals <= 0 || idxEquals == sItem.length() - 1) {
Expand All @@ -154,6 +161,22 @@ public void load(StringProperties properties, IRelativePathResolver resolver) th
customPrefixesMap.put(sPrefix, sURI);
}
}

this.languagePreference.clear();
String sLanguagePreference = properties.getProperty(PROPERTY_LANGUAGE_PREFERENCE, "").strip();
if (!sLanguagePreference.isEmpty()) {
for (String tag : sLanguagePreference.split(",")) {
tag = tag.strip();
if (isValidLanguageTag(tag)) {
this.languagePreference.add(tag);
} else {
throw new EolModelLoadingException(
new IllegalArgumentException(
String.format("'%s' is not a valid BCP 47 tag", tag)
), this);
}
}
}

load();
}
Expand Down Expand Up @@ -300,6 +323,10 @@ public void setUri(String uri) {
public Map<String, String> getCustomPrefixesMap() {
return this.customPrefixesMap;
}

public List<String> getLanguagePreference() {
return languagePreference;
}

/**
* <p>
Expand Down Expand Up @@ -338,4 +365,10 @@ public String getPrefix(String namespaceURI) {
}
return model.getNsURIPrefix(namespaceURI);
}

// Using Java's Locale class to check that tags conform to bcp47 structure
public static boolean isValidLanguageTag (String bcp47tag) {
boolean isValidBCP47 = !("und".equals(Locale.forLanguageTag(bcp47tag).toLanguageTag()));
return isValidBCP47;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ public static RDFQualifiedName from(String prefix, String nsURI, String localNam
public RDFQualifiedName withLocalName(String newLocalName) {
return new RDFQualifiedName(prefix, namespaceURI, newLocalName, languageTag);
}

public RDFQualifiedName withLanguageTag(String newLanguageTag) {
return new RDFQualifiedName(prefix, namespaceURI, localName, newLanguageTag);
}

@Override
public String toString() {
Expand Down
Loading

0 comments on commit f05488b

Please sign in to comment.