private void splitJourneyLocation( ConcurrentMap<String, IRI> variableTypes, List<LDObject> journeyLocation, List<LDObject> journeyDatas, BindingSet bindings) { LDObject locationsData = new LDObject(); LDObject journeyData = new LDObject(); bindings .getBindingNames() .stream() .forEach( bindingName -> { org.openrdf.model.Value value = bindings.getBinding(bindingName).getValue(); QueryResultsParser.updateVariableTypes(variableTypes, bindingName, value); if (Arrays.asList("id", "creationDate", "name", "status").contains(bindingName)) { journeyData.addKeyValue(new KeyValue(bindingName, value.stringValue())); } else { locationsData.addKeyValue(new KeyValue(bindingName, value.stringValue())); } if ("locationId".equalsIgnoreCase(bindingName)) { journeyData.addKeyValue(new KeyValue(bindingName, value.stringValue())); } }); journeyLocation.add(locationsData); journeyDatas.add(journeyData); }
public static void main(String[] args) { // create a graph with type inferencing SimpleSesameGraph g = new SimpleSesameGraph(true); // //load the film schema and the example data // g.addFile("../roadstead_ontologies/film-ontology.owl", SimpleSesameGraph.RDFXML); // try loading the geopolitical ontology g.addURI("http://aims.fao.org/aos/geopolitical.owl"); // List<HashMap<Object, Value>> solutions = g.runSPARQL("SELECT ?who WHERE { " + // "?who <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> // <http://roadstead.org/film#Person> ." + // "}"); /* Here we are looking for the names of all the things with a name */ List<HashMap<Object, Value>> solutions = g.runSPARQL( "SELECT ?name WHERE { " + "?what <http://aims.fao.org/aos/geopolitical.owl#territory> ?name ." + "?what <http://aims.fao.org/aos/geopolitical.owl#nameListEN> ?name ." + "}"); for (HashMap<Object, Value> object : solutions) { for (Value value : object.values()) { System.out.println("country: " + value.stringValue()); } } }
private Pair toPair(Edge e, Graph graph) { URI predicate = e.getPredicate(); Value object = e.getObject(); String value = null; if (object instanceof Literal) { Literal literal = (Literal) object; String language = literal.getLanguage(); URI type = literal.getDatatype(); if (type.equals(XMLSchema.STRING)) { type = null; } StringBuilder builder = new StringBuilder(); builder.append('"'); builder.append(literal.getLabel()); builder.append('"'); if (language != null) { builder.append('@'); builder.append(language); } else if (type != null) { builder.append('^'); builder.append(type.stringValue()); } value = builder.toString(); } else if (object instanceof URI) { value = object.stringValue(); } else { Resource id = (Resource) object; Vertex v = graph.getVertex(id); value = createHash(predicate, v); } return new Pair(predicate, value); }
private void writeVersion2(final ObjectOutput out) throws IOException { assert iv2val.size() == val2iv.size(); // compute a checksum on the hash codes of the URIs. long checksum = 0; for (Value value : val2iv.keySet()) { checksum += value.hashCode(); } // write on the #of declarations. LongPacker.packLong(out, decls.size()); // write on the #of values. LongPacker.packLong(out, val2iv.size()); // write out the checksum. out.writeLong(checksum); // The namespace of the KB instance. out.writeUTF(valueFactory.getNamespace()); // for (VocabularyDecl decl : decls) { // // // The class name of the vocabulary declaration. // out.writeUTF(decl.getClass().getName()); // // } }
public Collection<String> getIntersectionOf(String startingClass) throws RepositoryException, MalformedQueryException, QueryEvaluationException { Set<String> intersectionOfClasses = new HashSet<>(); RepositoryConnection con = this.repository.getConnection(); try { TupleQuery intersectionOfQuery = con.prepareTupleQuery( QueryLanguage.SPARQL, "SELECT ?c WHERE { ?c owl:intersectionOf ?l . " + "?l rdf:rest*/rdf:first <" + startingClass + "> .}"); TupleQueryResult intersectionOfResult = intersectionOfQuery.evaluate(); try { while (intersectionOfResult.hasNext()) { BindingSet bindingSet = intersectionOfResult.next(); Value name = bindingSet.getValue("c"); intersectionOfClasses.add(name.toString()); // System.out.println("intersections Ofs : " + name); } } finally { intersectionOfResult.close(); } } finally { con.close(); } return intersectionOfClasses; }
public Collection<String> getAllDisjointProperties(String startingProperty) throws RepositoryException, MalformedQueryException, QueryEvaluationException { Set<String> allDisjointProperties = new HashSet<>(); RepositoryConnection con = this.repository.getConnection(); try { TupleQuery allDisjointPropertiesQuery = con.prepareTupleQuery( QueryLanguage.SPARQL, "SELECT ?items " + "WHERE { ?y a owl:AllDisjointProperties ." + "?y owl:members ?members ." + "?members rdf:rest*/rdf:first <" + startingProperty + "> ." + "?members rdf:rest*/rdf:first ?items ." + "FILTER (?items != <" + startingProperty + ">) .}"); TupleQueryResult allDisjointPropertiesResult = allDisjointPropertiesQuery.evaluate(); try { while (allDisjointPropertiesResult.hasNext()) { BindingSet bindingSet = allDisjointPropertiesResult.next(); Value name = bindingSet.getValue("items"); allDisjointProperties.add(name.toString()); } } finally { allDisjointPropertiesResult.close(); } } finally { con.close(); } return allDisjointProperties; }
public void tupleQuery() throws QueryEvaluationException, RepositoryException, MalformedQueryException { // /query repo // con.setNamespace("onto", // "<http://it.unibz.krdb/obda/ontologies/test/translation/onto2.owl#>"); // System.out.println(con.getNamespaces().next().toString()); String queryString = "PREFIX : \n<http://it.unibz.krdb/obda/ontologies/test/translation/onto2.owl#>\n " + "SELECT ?x ?y WHERE { ?x a :Person. ?x :age ?y } "; // String queryString = // "SELECT ?x ?y WHERE { ?x a onto:Person. ?x onto:age ?y } "; TupleQuery tupleQuery = (con).prepareTupleQuery(QueryLanguage.SPARQL, queryString); TupleQueryResult result = tupleQuery.evaluate(); System.out.println(result.getBindingNames()); while (result.hasNext()) { BindingSet bindingSet = result.next(); Value valueOfX = bindingSet.getValue("x"); Literal valueOfY = (Literal) bindingSet.getValue("y"); System.out.println(valueOfX.stringValue() + ", " + valueOfY.floatValue()); } result.close(); }
private RDFRectangle toRectangle(StatementPattern pattern, BindingSet bindings) { Value sVal = pattern.getSubjectVar().getValue(); Value pVal = pattern.getPredicateVar().getValue(); Value oVal = pattern.getObjectVar().getValue(); RDFURIRange subjectRange; List<String> list = new ArrayList<String>(); if (sVal == null) { if (bindings.hasBinding(pattern.getSubjectVar().getName())) list.add(bindings.getValue(pattern.getSubjectVar().getName()).stringValue()); } else list.add(sVal.stringValue()); if (!list.isEmpty()) subjectRange = new RDFURIRange(list); else subjectRange = new RDFURIRange(); ExplicitSetRange<URI> predicateRange; Set<URI> set = new HashSet<URI>(); if (pVal == null) { if (bindings.hasBinding(pattern.getPredicateVar().getName())) set.add((URI) bindings.getValue(pattern.getPredicateVar().getName())); } else set.add((URI) pVal); if (!set.isEmpty()) predicateRange = new ExplicitSetRange<URI>(set); else predicateRange = new ExplicitSetRange<>(); RDFValueRange objectRange = new RDFValueRange(); if (oVal == null) { if (bindings.hasBinding(pattern.getObjectVar().getName())) objectRange = fillObjectRange(bindings.getValue(pattern.getObjectVar().getName())); } else objectRange = fillObjectRange(oVal); return new RDFRectangle(subjectRange, predicateRange, objectRange); }
/** * Extract content value from a term type resource. * * @return * @throws InvalidR2RMLStructureException */ private static Value extractValueFromTermMap( SesameDataSet r2rmlMappingGraph, Resource termType, Enum term) throws InvalidR2RMLStructureException { URI p = getTermURI(r2rmlMappingGraph, term); List<Statement> statements = r2rmlMappingGraph.tuplePattern(termType, p, null); if (statements.isEmpty()) { return null; } if (statements.size() > 1) { throw new InvalidR2RMLStructureException( "[RMLMappingFactory:extractValueFromTermMap] " + termType + " has too many " + term + " predicate defined."); } Value result = statements.get(0).getObject(); log.debug( "[RMLMappingFactory:extractValueFromTermMap] Extracted " + term + " : " + result.stringValue()); return result; }
/** * Finds the resource object matching the pattern <code>(s p _)</code>, asserts to find exactly * one result. * * @param s subject. * @param p predicate. * @return matching object. * @throws RepositoryException */ protected Resource findObjectAsResource(Resource s, URI p) throws RepositoryException { final Value v = findObject(s, p); try { return (Resource) v; } catch (ClassCastException cce) { Assert.fail("Expected resource object, found: " + v.getClass().getSimpleName()); throw new IllegalStateException(); } }
private void addToUrlList(Value iri) { try { URI uri = new URI(iri.stringValue()); if (uri.getScheme().startsWith("http")) { httpURIs.add(pruneFragment(uri)); } } catch (URISyntaxException e) { invalidResources.add(iri.toString()); } }
private Value copy(Value value) { if (value instanceof IRI) { return createIRI(value.stringValue()); } else if (value instanceof Literal) { Literal lit = (Literal) value; if (Literals.isLanguageLiteral(lit)) { return createLiteral(value.stringValue(), lit.getLanguage().orElse(null)); } else { return createLiteral(value.stringValue(), lit.getDatatype()); } } else { return createBNode(value.stringValue()); } }
public static void main(String[] args) throws Exception { File dataDir = new File(args[0]); ValueStore valueStore = new ValueStore(dataDir); int maxID = valueStore.dataStore.getMaxID(); for (int id = 1; id <= maxID; id++) { byte[] data = valueStore.dataStore.getData(id); if (valueStore.isNamespaceData(data)) { String ns = valueStore.data2namespace(data); System.out.println("[" + id + "] " + ns); } else { Value value = valueStore.data2value(id, data); System.out.println("[" + id + "] " + value.toString()); } } }
public boolean matches(final Vertex vertex, final Value value) { String kind = (String) vertex.getProperty(KIND); String val = (String) vertex.getProperty(VALUE); if (value instanceof URI) { return kind.equals(URI) && val.equals(value.stringValue()); } else if (value instanceof Literal) { if (kind.equals(LITERAL)) { if (!val.equals(((Literal) value).getLabel())) { return false; } String type = (String) vertex.getProperty(TYPE); String lang = (String) vertex.getProperty(LANG); URI vType = ((Literal) value).getDatatype(); String vLang = ((Literal) value).getLanguage(); return null == type && null == vType && null == lang && null == vLang || null != type && null != vType && type.equals(vType.stringValue()) || null != lang && null != vLang && lang.equals(vLang); } else { return false; } } else if (value instanceof BNode) { return kind.equals(BNODE) && ((BNode) value).getID().equals(val); } else { throw new IllegalStateException("value of unexpected kind: " + value); } }
/** * Insert Triple/Statement into graph * * @param s subject uriref * @param p predicate uriref * @param o value object (URIref or Literal) * @param contexts varArgs context objects (use default graph if null) */ public void add(Resource s, URI p, Value o, Resource... contexts) { if (log.isDebugEnabled()) log.debug( "[SesameDataSet:add] Add triple (" + s.stringValue() + ", " + p.stringValue() + ", " + o.stringValue() + ")."); try { RepositoryConnection con = currentRepository.getConnection(); try { ValueFactory myFactory = con.getValueFactory(); Statement st = myFactory.createStatement((Resource) s, p, (Value) o); con.add(st, contexts); con.commit(); } catch (Exception e) { e.printStackTrace(); } finally { con.close(); } } catch (Exception e) { // handle exception } }
public Vertex addVertex(final Value value) { Vertex v = graph.addVertex(null); if (value instanceof URI) { v.setProperty(KIND, URI); v.setProperty(VALUE, value.stringValue()); } else if (value instanceof Literal) { Literal l = (Literal) value; v.setProperty(KIND, LITERAL); v.setProperty(VALUE, l.getLabel()); if (null != l.getDatatype()) { v.setProperty(TYPE, l.getDatatype().stringValue()); } if (null != l.getLanguage()) { v.setProperty(LANG, l.getLanguage()); } } else if (value instanceof BNode) { BNode b = (BNode) value; v.setProperty(KIND, BNODE); v.setProperty(VALUE, b.getID()); } else { throw new IllegalStateException("value of unexpected type: " + value); } return v; }
/** * Sorts in the order nulls>BNodes>URIs>Literals * * <p>This is due to the fact that nulls are only applicable to contexts, and according to the * OpenRDF documentation, the type of the null cannot be sufficiently distinguished from any other * Value to make an intelligent comparison to other Values * * <p>http://www.openrdf.org/doc/sesame2/api/org/openrdf/OpenRDFUtil.html#verifyContextNotNull(org. * openrdf.model.Resource...) * * <p>BNodes are sorted according to the lexical compare of their identifiers, which provides a * way to sort statements with the same BNodes in the same positions, near each other * * <p>BNode sorting is not specified across sessions */ @Override public int compare(final Value first, final Value second) { if (first == null) { if (second == null) { return ValueComparator.EQUALS; } else { return ValueComparator.BEFORE; } } else if (second == null) { // always sort null Values before others, so if the second is null, but the first // wasn't, sort the first after the second return ValueComparator.AFTER; } if (first == second || first.equals(second)) { return ValueComparator.EQUALS; } if (first instanceof BNode) { if (second instanceof BNode) { // if both are BNodes, sort based on the lexical value of the internal ID // Although this sorting is not guaranteed to be consistent across sessions, // it provides a consistent sorting of statements in every case // so that statements with the same BNode are sorted near each other return ((BNode) first).getID().compareTo(((BNode) second).getID()); } else { return ValueComparator.BEFORE; } } else if (second instanceof BNode) { // sort BNodes before other things, and first was not a BNode return ValueComparator.AFTER; } else if (first instanceof URI) { if (second instanceof URI) { return ((URI) first).stringValue().compareTo(((URI) second).stringValue()); } else { return ValueComparator.BEFORE; } } else if (second instanceof URI) { // sort URIs before Literals return ValueComparator.AFTER; } // they must both be Literal's, so sort based on the lexical value of the Literal else { return first.stringValue().compareTo(second.stringValue()); } }
private String getrawDatasetId(Value rawDatasetUrl) { String dataset = rawDatasetUrl.stringValue(); int datasetOffset = dataset.lastIndexOf("dataset"); if (datasetOffset >= 0) { return dataset.substring(datasetOffset + 8); } return dataset.substring(dataset.lastIndexOf("/") + 1); }
public NativeValue getNativeValue(Value value) { if (value instanceof Resource) { return getNativeResource((Resource) value); } else if (value instanceof Literal) { return getNativeLiteral((Literal) value); } else { throw new IllegalArgumentException("Unknown value type: " + value.getClass()); } }
private Response get(URI user) { if (userService.isAnonymous(user)) { AccountPoJo apj = new AccountPoJo(Namespaces.ANONYMOUS_LOGIN, user.stringValue()); return Response.ok(apj, Namespaces.MIME_TYPE_JSON) .location(java.net.URI.create(user.stringValue())) .build(); } try { RepositoryConnection conn = sesameService.getConnection(); try { final UserAccount a = accountService.getAccount(user); if (a != null) { AccountPoJo apj = new AccountPoJo(a.getLogin(), a.getWebId()); apj.setRoles(a.getRoles()); for (Statement t : ResourceUtils.listOutgoing(conn, conn.getValueFactory().createURI(a.getWebId()))) { String prop = t.getPredicate().stringValue(); if (prop.startsWith(Namespaces.NS_FOAF)) { Value object = t.getObject(); if (object instanceof org.openrdf.model.URI) { apj.setFoaf(prop, String.format("<%s>", object)); } else if (object instanceof Literal) { apj.setFoaf(prop, object.toString()); } } } return Response.ok(apj, Namespaces.MIME_TYPE_JSON) .location(java.net.URI.create(user.stringValue())) .build(); } return Response.status(Status.NOT_FOUND) .entity("Could not find account data of " + user) .build(); } finally { conn.commit(); conn.close(); } } catch (RepositoryException e) { // This must not happen! return Response.serverError().entity(e).build(); } }
// this needs to run after the rest of the model has been added to the map private ArtifactFragment checkMapforRes( Map<Resource, ArtifactFragment> instanceRes2AFMap, Value cfTopRes, Resource cfInstanceModelRes) { ArtifactFragment retAF = null; for (ArtifactFragment resAF : instanceRes2AFMap.values()) { if (resAF.toString().equals(cfTopRes.toString())) { if (resAF instanceof MethodInvocationModel) retAF = resAF; } } return retAF; }
/** * Extract content values from a term type resource. * * @return * @throws InvalidR2RMLStructureException */ private static Set<Value> extractValuesFromResource( SesameDataSet r2rmlMappingGraph, Resource termType, Enum term) throws InvalidR2RMLStructureException { URI p = getTermURI(r2rmlMappingGraph, term); List<Statement> statements = r2rmlMappingGraph.tuplePattern(termType, p, null); if (statements.isEmpty()) { return null; } Set<Value> values = new HashSet<Value>(); for (Statement statement : statements) { Value value = statement.getObject(); log.debug( "[RMLMappingFactory:extractURIsFromTermMap] Extracted " + term + " : " + value.stringValue()); values.add(value); } return values; }
public Vertex findVertex(final Value value) { CloseableSequence<Vertex> i = values.get(VALUE, value.stringValue()); try { while (i.hasNext()) { Vertex v = i.next(); if (matches(v, value)) { return v; } } return null; } finally { i.close(); } }
public Vertex findVertex(final Value value) { Iterator<Vertex> i = store.graph.getVertices(VALUE, value.stringValue()).iterator(); // TODO: restore the close() // try { while (i.hasNext()) { Vertex v = i.next(); if (matches(v, value)) { return v; } } return null; // } finally { // i.close(); // } }
private void storeStatement(Resource subj, URI pred, Value obj, Resource... contexts) throws SailException { if (subj.equals(currentTrx)) { subj = getTrx(); } if (obj.equals(currentTrx)) { obj = getTrx(); } if (contexts != null && contexts.length == 1) { if (currentTrx.equals(contexts[0])) { contexts[0] = getTrx(); } } else if (contexts != null) { for (int i = 0; i < contexts.length; i++) { if (currentTrx.equals(contexts[i])) { contexts[i] = getTrx(); } } } if (contexts == null || contexts.length == 0 || contexts.length == 1 && contexts[0] == null) { addRevision(subj); super.addStatement(subj, pred, obj, getTrx()); } else if (contexts.length == 1) { if (contexts[0].equals(trx)) { addRevision(subj); } super.addStatement(subj, pred, obj, contexts); Resource ctx = contexts[0]; if (isURI(ctx) && !ctx.equals(trx) && modified.add(ctx)) { addMetadata(currentTrx, MODIFIED, ctx, currentTrx); } } else { for (Resource ctx : contexts) { if (ctx == null || ctx.equals(trx)) { addRevision(subj); break; } } super.addStatement(subj, pred, obj, contexts); for (Resource ctx : contexts) { if (isURI(ctx) && !ctx.equals(trx) && modified.add(ctx)) { addMetadata(currentTrx, MODIFIED, ctx, currentTrx); } } } }
@Override public synchronized void addStatement(Resource subj, URI pred, Value obj, Resource... contexts) throws SailException { flushArchive(); if (subj.equals(currentTrx) || obj.equals(currentTrx) && !Audit.REVISION.equals(pred)) { if (contexts == null) { addMetadata(subj, pred, obj, null); } else if (contexts.length == 1) { addMetadata(subj, pred, obj, contexts[0]); } else { for (Resource ctx : contexts) { addMetadata(subj, pred, obj, ctx); } } } else { storeStatement(subj, pred, obj, contexts); } }
@Override public String toString() { StringBuilder sb = new StringBuilder(128); sb.append(alias).append(".").append(column); sb.append(" (name=").append(name); if (value != null) { sb.append(", value=").append(value.toString()); } sb.append(")"); if (index > 0) { sb.append("#").append(index); } return sb.toString(); }
private static boolean statementsMatch( Statement st1, Statement st2, Map<BNode, BNode> bNodeMapping) { URI pred1 = st1.getPredicate(); URI pred2 = st2.getPredicate(); if (!pred1.equals(pred2)) { // predicates don't match return false; } Resource subj1 = st1.getSubject(); Resource subj2 = st2.getSubject(); if (!(subj1 instanceof BNode)) { if (!subj1.equals(subj2)) { // subjects are not bNodes and don't match return false; } } else { // subj1 instanceof BNode BNode mappedBNode = bNodeMapping.get(subj1); if (mappedBNode != null) { // bNode 'subj1' was already mapped to some other bNode if (!subj2.equals(mappedBNode)) { // 'subj1' and 'subj2' do not match return false; } } else { // 'subj1' was not yet mapped. we need to check if 'subj2' is a // possible mapping candidate if (bNodeMapping.containsValue(subj2)) { // 'subj2' is already mapped to some other value. return false; } } } Value obj1 = st1.getObject(); Value obj2 = st2.getObject(); if (!(obj1 instanceof BNode)) { if (!obj1.equals(obj2)) { // objects are not bNodes and don't match return false; } } else { // obj1 instanceof BNode BNode mappedBNode = bNodeMapping.get(obj1); if (mappedBNode != null) { // bNode 'obj1' was already mapped to some other bNode if (!obj2.equals(mappedBNode)) { // 'obj1' and 'obj2' do not match return false; } } else { // 'obj1' was not yet mapped. we need to check if 'obj2' is a // possible mapping candidate if (bNodeMapping.containsValue(obj2)) { // 'obj2' is already mapped to some other value. return false; } } } return true; }
/** Copied from org.openrdf.query.QueryResultUtil */ private static boolean bindingSetsMatch(final BindingSet bs1, final BindingSet bs2) { if (bs1.size() != bs2.size()) { return false; } for (Binding binding1 : bs1) { Value value1 = binding1.getValue(); Value value2 = bs2.getValue(binding1.getName()); if ((value1 instanceof BNode) && (value2 instanceof BNode)) { // BNode mappedBNode = bNodeMapping.get(value1); // // if (mappedBNode != null) { // // bNode 'value1' was already mapped to some other bNode // if (!value2.equals(mappedBNode)) { // // 'value1' and 'value2' do not match // return false; // } // } else { // // 'value1' was not yet mapped, we need to check if 'value2' // // is a // // possible mapping candidate // if (bNodeMapping.containsValue(value2)) { // // 'value2' is already mapped to some other value. // return false; // } // } return value1.equals(value2); } else { // values are not (both) bNodes if ((value1 instanceof Literal) && (value2 instanceof Literal)) { // do literal value-based comparison for supported datatypes Literal leftLit = (Literal) value1; Literal rightLit = (Literal) value2; URI dt1 = leftLit.getDatatype(); URI dt2 = rightLit.getDatatype(); if ((dt1 != null) && (dt2 != null) && dt1.equals(dt2) && XMLDatatypeUtil.isValidValue(leftLit.getLabel(), dt1) && XMLDatatypeUtil.isValidValue(rightLit.getLabel(), dt2)) { Integer compareResult = null; if (dt1.equals(XMLSchema.DOUBLE)) { compareResult = Double.compare(leftLit.doubleValue(), rightLit.doubleValue()); } else if (dt1.equals(XMLSchema.FLOAT)) { compareResult = Float.compare(leftLit.floatValue(), rightLit.floatValue()); } else if (dt1.equals(XMLSchema.DECIMAL)) { compareResult = leftLit.decimalValue().compareTo(rightLit.decimalValue()); } else if (XMLDatatypeUtil.isIntegerDatatype(dt1)) { compareResult = leftLit.integerValue().compareTo(rightLit.integerValue()); } else if (dt1.equals(XMLSchema.BOOLEAN)) { Boolean leftBool = Boolean.valueOf(leftLit.booleanValue()); Boolean rightBool = Boolean.valueOf(rightLit.booleanValue()); compareResult = leftBool.compareTo(rightBool); } else if (XMLDatatypeUtil.isCalendarDatatype(dt1)) { XMLGregorianCalendar left = leftLit.calendarValue(); XMLGregorianCalendar right = rightLit.calendarValue(); compareResult = left.compare(right); } if (compareResult != null) { if (compareResult.intValue() != 0) { return false; } } else if (!value1.equals(value2)) { return false; } } else if (!value1.equals(value2)) { return false; } } else if (!value1.equals(value2)) { return false; } } } return true; }
private String getString(Value v) { if (v != null) { return v.stringValue(); } return null; }