package org.datacite.conres.model;
import nu.xom.*;
import org.datacite.conres.view.Representation;
import javax.ws.rs.core.MediaType;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URI;
import java.util.*;
import org.datacite.conres.Configuration;
/**
* Represents model passed to Representation
*/
public class Model {
private byte[] xml;
private String doi;
private Map<MediaType, URI> userMedia;
private Document document;
private List<String> creators;
private String publicationYear;
private List<Pair> titles;
private String publisher;
private List<Pair> resourceTypes;
private List<Pair> descriptions;
private List<Pair> subjects;
private List<String> sizes;
private List<String> rights;
private List<Pair> dates;
private String language;
private List<String> formats;
private String version;
private List<Pair> alternateIdentifiers;
private List<Pair> relatedIdentifiers;
private List<Pair> contributors;
private String allocatorName;
private String datacentreName;
private boolean xmlPresent;
private String contextPath;
private String cslStyle;
private String cslLocale;
private Date uploaded;
private String siteGa;
public Model(String doi,
byte[] xml,
Map<MediaType, URI> userMedia,
String contextPath,
String allocatorName,
String datacentreName,
String cslStyle,
String cslLocale,
Date uploaded) {
this.doi = doi;
this.xmlPresent = xml!=null && !"".equals(xml);
this.userMedia = userMedia;
this.contextPath = contextPath;
this.allocatorName = allocatorName;
this.datacentreName = datacentreName;
this.cslStyle = cslStyle;
this.cslLocale = cslLocale;
this.uploaded = uploaded;
if (xml != null && xml.length > 0){
this.xml = new byte[xml.length];
System.arraycopy(xml, 0, this.xml , 0, xml.length);
Builder parser = new Builder();
try {
InputStream inputStream = new ByteArrayInputStream(this.xml);
document = parser.build(inputStream, null);
} catch (Exception e) {
throw new RuntimeException(e);
}
this.creators = extractList("creatorName");
this.publicationYear = extractText("publicationYear");
this.titles = extractPairs("title", "titleType");
this.publisher = extractText("publisher");
this.resourceTypes = extractPairs("resourceType", "resourceTypeGeneral");
this.descriptions = extractPairs("description", "descriptionType");
this.subjects = extractPairs("subject", "subjectScheme");
this.sizes = extractList("size");
this.rights = extractList("rights");
this.dates = extractPairs("date", "dateType");
this.language = extractText("language");
this.formats = extractList("format");
this.version = extractText("version");
this.alternateIdentifiers = extractPairs("alternateIdentifier", "alternateIdentifierType");
this.relatedIdentifiers = extractRelatedIds();
this.contributors = extractContributors();
}
this.siteGa = Configuration.APP_GOOGLE_ANALYTICS;
}
private List<Pair> extractRelatedIds() {
Nodes nodes = document.query("//*[local-name() = 'relatedIdentifier']");
List<Pair> result = new ArrayList<Pair>();
for(int i = 0; i < nodes.size(); i++){
Node node = nodes.get(i);
Element el = (Element) node;
Attribute idType = el.getAttribute("relatedIdentifierType");
Attribute relType = el.getAttribute("relationType");
String idTypeStr = "";
String relTypeStr = "";
if (relType != null)
relTypeStr = relType.getValue().trim();
if (idType != null)
idTypeStr = idType.getValue().trim();
result.add(new Pair(relTypeStr, idTypeStr.toLowerCase() + ":" + node.getValue().trim()));
}
return result;
}
private List<Pair> extractContributors() {
String nameSpace = document.getRootElement().getNamespaceURI();
Nodes nodes = document.query("//*[local-name() = 'contributor']");
List<Pair> result = new ArrayList<Pair>();
for(int i = 0; i < nodes.size(); i++){
Node node = nodes.get(i);
Element el = (Element) node;
Attribute conType = el.getAttribute("contributorType");
String conTypeStr = "";
if (conType != null)
conTypeStr = conType.getValue().trim();
Element contributorName = el.getFirstChildElement("contributorName", nameSpace);
String conString = contributorName.getValue().trim();
Element nameIdentifier = el.getFirstChildElement("nameIdentifier", nameSpace);
if (nameIdentifier != null) {
Attribute scheme = nameIdentifier.getAttribute("nameIdentifierScheme");
String schemeStr = "";
if (scheme != null)
schemeStr = scheme.getValue().trim() + ": ";
conString += " (" + schemeStr + nameIdentifier.getValue().trim() + ")";
}
Element affiliation = el.getFirstChildElement("affiliation", nameSpace);
if (affiliation != null)
conString += ", " + affiliation.getValue().trim();
result.add(new Pair(conTypeStr, conString));
}
return result;
}
private List<Pair> extractPairs(String elementName, String attributeName) {
List<Pair> result = new ArrayList<Pair>();
Nodes nodes = document.query("//*[local-name() = '" + elementName + "']");
for(int i = 0; i < nodes.size(); i++){
Node node = nodes.get(i);
Element el = (Element) node;
Attribute attribute = el.getAttribute(attributeName);
String attr = "";
if (attribute != null)
attr = attribute.getValue();
result.add(new Pair(attr, getInnerXML(node).trim()));
}
return result;
}
private String getInnerXML(Node node) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < node.getChildCount(); i++) {
sb.append(node.getChild(i).toXML());
}
return sb.toString();
}
private String extractText(String elementName) {
StringBuilder sb = new StringBuilder();
Nodes nodes = document.query("//*[local-name() = '" + elementName + "']");
for(int i = 0; i < nodes.size(); i++){
Node node = nodes.get(i);
sb.append(node.getValue().trim());
}
return sb.toString();
}
private List<String> extractList(String elementName){
List<String> result = new ArrayList<String>();
Nodes nodes = document.query("//*[local-name() = '" + elementName + "']");
for(int i = 0; i < nodes.size(); i++){
Node node = nodes.get(i);
result.add(node.getValue().trim());
}
return result;
}
public String getDoi() {
return doi;
}
public byte[] getXml() {
return xml;
}
public List<String> getCreators() {
return creators;
}
public String getPublicationYear() {
return publicationYear;
}
public List<Pair> getTitles() {
return titles;
}
public String getPublisher() {
return publisher;
}
public List<Pair> getResourceTypes() {
return resourceTypes;
}
public List<Pair> getDescriptions() {
return descriptions;
}
public List<Pair> getSubjects() {
return subjects;
}
public List<String> getSizes() {
return sizes;
}
public List<String> getRights() {
return rights;
}
public List<Pair> getDates() {
return dates;
}
public String getLanguage() {
return language;
}
public List<String> getFormats() {
return formats;
}
public String getVersion() {
return version;
}
public List<Pair> getAlternateIdentifiers() {
return alternateIdentifiers;
}
public List<Pair> getRelatedIdentifiers() {
return relatedIdentifiers;
}
public List<Pair> getContributors() {
return contributors;
}
public String getContextPath() {
return contextPath;
}
public String getAllocatorName() {
return allocatorName;
}
public String getDatacentreName() {
return datacentreName;
}
public boolean isXmlPresent() {
return xmlPresent;
}
public String getCslStyle() {
return cslStyle;
}
public String getCslLocale() {
return cslLocale;
}
public Map<MediaType, URI> getUserMedia() {
return userMedia;
}
public String getFirstTitle() {
if (titles == null || titles.size() == 0)
return null;
return titles.get(0).getValue();
}
public List<String> getAllMedia(){
List<String> allSupportedTypes = new ArrayList<String >();
for (MediaType m : userMedia.keySet()) {
allSupportedTypes.add(m.toString());
}
if (xmlPresent)
for(Representation c: Representation.values()) {
allSupportedTypes.add(c.toString());
}
return allSupportedTypes;
}
public Date getUploaded() {
return uploaded;
}
public String getSiteGa() {
return siteGa;
}
public static final String escapeLatex(String text) {
StringBuilder sb=new StringBuilder(text.length());
boolean nl=false;
for (int i=0,c=text.length(); i<c; i++) {
char ch=text.charAt(i);
if (ch!=13 && ch!=10 && nl) {
sb.append("\\\\\n");
nl=false;
}
switch (ch) {
case '\u00E4': sb.append("{\\\"a}"); break;
case '\u00F6': sb.append("{\\\"o}"); break;
case '\u00FC': sb.append("{\\\"u}"); break;
case '\u00EB': sb.append("{\\\"e}"); break;
case '\u00EF': sb.append("{\\\"i}"); break;
case 196: sb.append("{\\\"A}"); break;
case 214: sb.append("{\\\"O}"); break;
case 220: sb.append("{\\\"U}"); break;
case 203: sb.append("{\\\"E}"); break;
case 207: sb.append("{\\\"I}"); break;
case 225: sb.append("{\\'a}"); break;
case 243: sb.append("{\\'o}"); break;
case 250: sb.append("{\\'u}"); break;
case 233: sb.append("{\\'e}"); break;
case 237: sb.append("{\\'i}"); break;
case 224: sb.append("{\\`a}"); break;
case 242: sb.append("{\\`o}"); break;
case 249: sb.append("{\\`u}"); break;
case 232: sb.append("{\\`e}"); break;
case 236: sb.append("{\\`i}"); break;
case 226: sb.append("{\\^a}"); break;
case 244: sb.append("{\\^o}"); break;
case 251: sb.append("{\\^u}"); break;
case 234: sb.append("{\\^e}"); break;
case 238: sb.append("{\\^i}"); break;
case 194: sb.append("{\\^A}"); break;
case 212: sb.append("{\\^O}"); break;
case 219: sb.append("{\\^U}"); break;
case 202: sb.append("{\\^E}"); break;
case 206: sb.append("{\\^I}"); break;
case 227: sb.append("{\\~a}"); break;
case 241: sb.append("{\\~n}"); break;
case 245: sb.append("{\\~o}"); break;
case 195: sb.append("{\\~A}"); break;
case 209: sb.append("{\\~N}"); break;
case 213: sb.append("{\\~O}"); break;
case '\u00DF': sb.append("{\\ss}"); break;
case '\u00A0': sb.append('~'); break; //
case '\u00BA':
case '\u00B0': sb.append("{\\textdegree}"); break;
case '"': sb.append("{\"}"); break;
case 13:
case 10:
nl=true;
break;
case '\'':
case '\u00B4':
case '`':
sb.append("{\'}"); break;
// simple escapes:
case '\\':
case '~':
case '$':
case '%':
case '^':
case '&':
case '{':
case '}':
case '_':
sb.append('\\').append(ch);
break;
default:
if (ch<0x80) {
sb.append(ch);
} else {
sb.append(String.format(Locale.ROOT, "{\\char\"%04X}", Integer.valueOf(ch)));
}
}
}
return sb.toString();
}
}