@Override public Window deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException { JsonNode node = jp.getCodec().readTree(jp); Double value = node.get("value").asDouble(); Window window = new Window(value); if (node.has("bounds")) { long lowerBound = node.get("bounds").get(0).asLong(); long upperBound = node.get("bounds").get(1).asLong(); window.withLowerBound(lowerBound).withUpperBound(upperBound); } return window; }
public static Criteria getCriteria(ObjectNode rudeCriteria) throws Exception { Criteria criteria = new Criteria(); if (rudeCriteria.has("criterions")) { ArrayNode criterions = (ArrayNode) rudeCriteria.get("criterions"); if (criterions != null) { for (Iterator<JsonNode> it = criterions.iterator(); it.hasNext();) { criteria.addCriterion(parseCriterion((ObjectNode) it.next())); } } } if (rudeCriteria.has("orders")) { ArrayNode orders = (ArrayNode) rudeCriteria.get("orders"); if (orders != null) { for (Iterator<JsonNode> it = orders.iterator(); it.hasNext();) { ObjectNode rudeCriterion = (ObjectNode) it.next(); Order order = new Order(JsonUtils.getString(rudeCriterion, "property"), JsonUtils.getBoolean(rudeCriterion, "desc")); criteria.addOrder(order); } } } return criteria; }
public String getExecLog(int execId, String jobName, String offset, String length) throws Exception { Map<String, String> paramsMap = new HashMap<>(); // TODO try with session id, if it expired, re-login paramsMap.put("ajax", "fetchExecJobLogs"); paramsMap.put("execid", String.valueOf(execId)); paramsMap.put("jobId", jobName); paramsMap.put("offset", offset); paramsMap.put("length", length); String url = AZKABAN_URL + "/executor"; String response = sendRequest(url, paramsMap, "get"); // retrieve from json JsonNode obj = jsonReader.readTree(response); String execLog = obj.get("data").asText(); return execLog; }
/** * Recursively process the execution info to get {@AzkabanJobExecRecord} * @param allJobs JsonNode in "nodes" field * @param flowExecId * @param flowPath Format : project_name:first_level_flow/sub_flow/sub_flow * @return */ private List<AzkabanJobExecRecord> parseJsonHelper(JsonNode allJobs, long flowExecId, String flowPath) { List<AzkabanJobExecRecord> results = new ArrayList<>(); for (JsonNode oneJob : allJobs) { if (oneJob.has("nodes")) { // is a subflow String subFlowName = oneJob.get("id").asText(); flowPath += "/" + subFlowName; results.addAll(parseJsonHelper(oneJob.get("nodes"), flowExecId, flowPath)); } else { String jobName = oneJob.get("id").asText(); long startTime = oneJob.get("startTime").asLong(); long endTime = oneJob.get("endTime").asLong(); String status = oneJob.get("status").asText(); AzkabanJobExecRecord azkabanJobExecRecord = new AzkabanJobExecRecord(appId, jobName, flowExecId, (int) (startTime / 1000), (int) (endTime / 1000), status, flowPath); results.add(azkabanJobExecRecord); } } return results; }
@Override public void flatMap(String tweetJsonStr, Collector<Tuple2<String, Integer>> collector) throws Exception { JsonNode tweetJson = mapper.readTree(tweetJsonStr); JsonNode entities = tweetJson.get("entities"); if (entities == null) return; JsonNode hashtags = entities.get("hashtags"); if (hashtags == null) return; for (Iterator<JsonNode> iter = hashtags.getElements(); iter.hasNext();) { JsonNode node = iter.next(); String hashtag = node.get("text").getTextValue(); if (hashtag.matches("\\w+")) { collector.collect(new Tuple2<>(hashtag, 1)); } } }
@Override public Directive deserialize(JsonParser jp, DeserializationContext ctx) throws IOException { ObjectReader reader = ObjectMapperUtil.instance().getObjectReader(); ObjectNode obj = (ObjectNode) reader.readTree(jp); Iterator<Map.Entry<String, JsonNode>> elementsIterator = obj.getFields(); String rawMessage = obj.toString(); DialogRequestIdHeader header = null; JsonNode payloadNode = null; ObjectReader headerReader = ObjectMapperUtil.instance().getObjectReader(DialogRequestIdHeader.class); while (elementsIterator.hasNext()) { Map.Entry<String, JsonNode> element = elementsIterator.next(); if (element.getKey().equals("header")) { header = headerReader.readValue(element.getValue()); } if (element.getKey().equals("payload")) { payloadNode = element.getValue(); } } if (header == null) { throw ctx.mappingException("Missing header"); } if (payloadNode == null) { throw ctx.mappingException("Missing payload"); } return createDirective(header, payloadNode, rawMessage); }
@Override public TopicRecord deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException { JsonNode node = jp.getCodec().readTree(jp); String topic = node.get("topic").asText(); long partition = node.get("partition").asLong(); long offset = node.get("offset").asLong(); long timestamp = node.get("timestamp").asLong(); String key = null; if (node.has("key")) { key = node.get("key").asText(); } Map<Object, Object> value = new ObjectMapper().readValue(node.get("value").toString(), Map.class); return new TopicRecord(topic, key, partition, offset, timestamp, value); }
public String search(String query) { try { String url = "?text=" + Utility.urlEncode(query) + "&confidence=" + confidence; HttpGet httpGet = new HttpGet(URL + url); httpGet.addHeader("Accept", "application/json"); HttpResponse response = client.execute(httpGet); // Error Scenario if(response.getStatusLine().getStatusCode() >= 400) { logger.error("Spotlight Service could not answer due to: " + response.getStatusLine()); return null; } else { String entities = EntityUtils.toString(response.getEntity()); JsonNode entity = new ObjectMapper().readTree(entities).get("Resources").get(0); return entity.get("@URI").getTextValue(); } } catch (Exception e) { e.printStackTrace(); } return null; }
private ArrayList<ResponseData> getCastOrCrew(String url, String type) { ArrayList<ResponseData> datas = new ArrayList<>(); try { JsonNode people = makeRequest(url).get(type); List<String> peopleNames = new ArrayList<>(); for(JsonNode person : people) { peopleNames.add(person.get("name").getTextValue()); } if (peopleNames.size() > ResponseData.MAX_DATA_SIZE) { peopleNames = peopleNames.subList(0, ResponseData.MAX_DATA_SIZE); } for (String personName : peopleNames) { String uri = new LookupService().search(personName); if(uri != null) { datas.add(sparql.getEntityInformation(uri)); } } } catch(Exception e) { e.printStackTrace(); } return datas; }
@Override public ProducedEventsResult deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException { JsonNode node = jp.getCodec().readTree(jp); if (node.isArray()) { List<ProducedEventResult> responses = new ArrayList<>(); Iterator<JsonNode> it = node.iterator(); while (it.hasNext()) { JsonNode n = it.next(); responses.add(new ProducedEventResult(n.get("created").asBoolean())); } return new ProducedEventsResult(responses); } else { String reason = node.get("reason").asText(); return new ProducedEventsResult(reason); } }
private Set<String> deserializeIdentifiers(final String aMultipleIdentifierKey, final String aSingleIdentifierKey, final JsonNode aRootNode) { final Set<String> results = new HashSet<>(); final JsonNode multiNode = aRootNode.get(aMultipleIdentifierKey); if (multiNode != null) { for (final JsonNode node : multiNode) { results.add(node.get(aSingleIdentifierKey).getValueAsText()); } } else { final JsonNode singleNode = aRootNode.get(aSingleIdentifierKey); if ( singleNode != null) { results.add(singleNode.getValueAsText()); } } return results; }
private String getHostId(String hostname) throws IOException { String hostId = null; URI uri = UriBuilder.fromUri(serverHostname) .path("api") .path(API_VERSION) .path("hosts") .build(); JsonNode hosts = getJsonNodeFromURIGet(uri); if (hosts != null) { // Iterate through the list of hosts, stopping once you've reached the requested hostname. for (JsonNode host : hosts) { if (host.get("hostname").getTextValue().equals(hostname)) { hostId = host.get("hostId").getTextValue(); break; } } } else { hostId = null; } return hostId; }
public static List<Parameter> parseParameters(JsonNode node){ JsonNode parametersNode=node.get("parameters"); if(parametersNode==null){ return null; } Iterator<JsonNode> iter=parametersNode.iterator(); List<Parameter> parameters=new ArrayList<Parameter>(); while(iter.hasNext()){ JsonNode parameterNode=iter.next(); Parameter param=new Parameter(); param.setName(getJsonValue(parameterNode, "name")); String type=getJsonValue(parameterNode, "type"); if(type!=null){ param.setType(Datatype.valueOf(type)); } String valueTypeText=getJsonValue(parameterNode, "valueType"); if(valueTypeText!=null){ param.setValue(parseValue(parameterNode)); } param.setValue(parseValue(parameterNode)); parameters.add(param); } return parameters; }
private List<Line> parseLines(JsonNode node){ JsonNode lineNodes=node.get("lines"); if(lineNodes==null){ return null; } List<Line> lines=new ArrayList<Line>(); Iterator<JsonNode> iter=lineNodes.iterator(); while(iter.hasNext()){ JsonNode jsonNode=iter.next(); Line line=new Line(); line.setFromNodeId(jsonNode.get("fromNodeId").getIntValue()); line.setToNodeId(jsonNode.get("toNodeId").getIntValue()); lines.add(line); } return lines; }
private CriteriaUnit parseCriteriaUnit(JsonNode unitNode) { CriteriaUnit unit=new CriteriaUnit(); JsonNode criteriaNode=unitNode.get("criteria"); if(criteriaNode!=null){ unit.setCriteria(parseCriteria(criteriaNode)); } JsonNode junctionTypeNode=unitNode.get("junctionType"); if(junctionTypeNode!=null){ unit.setJunctionType(JunctionType.valueOf(junctionTypeNode.getTextValue())); } JsonNode nextUnitNodes=unitNode.get("nextUnits"); if(nextUnitNodes!=null){ List<CriteriaUnit> nextUnits=new ArrayList<CriteriaUnit>(); Iterator<JsonNode> iter=nextUnitNodes.iterator(); while(iter.hasNext()){ JsonNode nextNode=iter.next(); nextUnits.add(parseCriteriaUnit(nextNode)); } unit.setNextUnits(nextUnits); } return unit; }
/** * Returns JSON format of a content node already mapped to a {@link org.codehaus.jackson.JsonNode}. * * @deprecated use {@link #waitExists(String, long, long)} and {@link #doGetJson(String, int, int...)} instead * @param path the path to the content node * @param depth the number of levels to go down the tree, -1 for infinity * @param waitMillis how long it should wait between requests * @param retryNumber number of retries before throwing an exception * @param expectedStatus list of allowed HTTP Status to be returned. If not set, * http status 200 (OK) is assumed. * @return a {@link org.codehaus.jackson.JsonNode} mapping to the requested content node. * @throws ClientException if something fails during request/response cycle * @throws InterruptedException to mark this operation as "waiting" */ @Deprecated public JsonNode getJsonNode(String path, int depth, final long waitMillis, final int retryNumber, int... expectedStatus) throws ClientException, InterruptedException { // check if path exist and wait if needed waitUntilExists(path, waitMillis, retryNumber); // check for infinity if (depth == -1) { path += ".infinity.json"; } else { path += "." + depth + ".json"; } // request the JSON for the page node SlingHttpResponse response = this.doGet(path); HttpUtils.verifyHttpStatus(response, HttpUtils.getExpectedStatus(SC_OK, expectedStatus)); return JsonUtils.getJsonNodeFromString(response.getContent()); }
private ArrayList<String> getListOfUncachedTrackIDs(JsonNode features) { ArrayList<String> missingTrackIDs = new ArrayList<String>(); for (JsonNode feature : features) { JsonNode attributes = feature.get("attributes"); JsonNode trackIDNode = attributes.get(trackIDField); if (trackIDNode != null) { String trackID = getTrackIdAsString(trackIDNode); if (!oidCache.containsKey(trackID)) { if (missingTrackIDs == null) missingTrackIDs = new ArrayList<String>(); if (!missingTrackIDs.contains(trackID)) missingTrackIDs.add(trackID); } } } return missingTrackIDs; }
private List<JsonNode> findBy(String key, String value, boolean onlyReturnFirstMatch, boolean arrayContainingMatch) { Iterator<JsonNode> nodes = root.get("data").getElements(); List<JsonNode> results = new LinkedList<>(); while(nodes.hasNext()) { JsonNode node = nodes.next(); if ((null != node.get(key)) && (node.get(key).isValueNode())) { final String valueNode = node.get(key).getTextValue(); if (arrayContainingMatch) { if (splitPseudoJsonValueArray(valueNode).contains(value)) { results.add(node); } } else { if (valueNode.equals(value)) { results.add(node); } } } } return results; }
/** * In order to query a namenode mxbean, a http connection in the form of * "http://hostname/jmx?qry=Hadoop:service=NameNode,name=NameNodeInfo" * is sent to namenode. JMX attributes are exposed via JmxJsonServelet on * the namenode side. */ private static JsonNode getProperty(String props, String propertyname) throws IOException { if (props == null || props.equals("") || propertyname == null || propertyname.equals("")) { return null; } ObjectMapper m = new ObjectMapper(); JsonNode rootNode = m.readValue(props, JsonNode.class); JsonNode jn = rootNode.get("beans").get(0).get(propertyname); return jn; }
/** * Parse the json of flow_data field from execution_flows. Use recursion to handle the nested case. * @param flowJson * @param flowExecId * @return * @throws IOException */ public List<AzkabanJobExecRecord> parseJson(String flowJson, long flowExecId) throws IOException { ObjectMapper mapper = new ObjectMapper(); JsonNode wholeFlow = mapper.readTree(flowJson); JsonNode allJobs = wholeFlow.get("nodes"); String flowPath = wholeFlow.get("projectName").asText() + ":" + wholeFlow.get("flowId").asText(); List<AzkabanJobExecRecord> results = parseJsonHelper(allJobs, flowExecId, flowPath); AzkabanJobExecUtil.sortAndSet(results); return results; }
private void injectDefaultValueIfAvailable(final JsonParser in, String fieldName) throws IOException { Field field = findField(schema, fieldName); if (field == null) { throw new AvroTypeException("Expected field name not found: " + fieldName); } JsonNode defVal = field.defaultValue(); if (defVal == null) { throw new AvroTypeException("Expected field name not found: " + fieldName); } List<JsonElement> result = new ArrayList<>(2); JsonParser traverse = defVal.traverse(); JsonToken nextToken; while ((nextToken = traverse.nextToken()) != null) { if (nextToken.isScalarValue()) { result.add(new JsonElement(nextToken, traverse.getText())); } else { result.add(new JsonElement(nextToken)); } } result.add(NULL_JSON_ELEMENT); if (currentReorderBuffer == null) { currentReorderBuffer = new ReorderBuffer(); } currentReorderBuffer.origParser = in; this.in = makeParser(result); }
public static void write(RecordEntry recordEntry, String oracleFullTableName, String topicName, String fileName, int maxFileSize, String msg) { checkFileSize(fileName, maxFileSize); DirtyRecordInfo dirtyRecordInfo = new DirtyRecordInfo(); dirtyRecordInfo.setOracleTable(oracleFullTableName); dirtyRecordInfo.setTopicName(topicName); dirtyRecordInfo.setShardId(recordEntry.getShardId()); dirtyRecordInfo.setErrorMessage(msg); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dirtyRecordInfo.setErrorTime(simpleDateFormat.format(new Date())); Map<String, String> record = Maps.newHashMap(); dirtyRecordInfo.setRecord(record); Field[] fields = recordEntry.getFields(); JsonNode jsonNode = recordEntry.toJsonNode(); ArrayNode arrayNode = (ArrayNode) jsonNode.get("Data"); for (int i = 0; i < recordEntry.getFieldCount(); i++) { record.put(fields[i].getName(), arrayNode.get(i).getTextValue()); } try { BufferedWriter bw = new BufferedWriter(new FileWriter(fileName, true)); bw.write(JsonHelper.beanToJson(dirtyRecordInfo) + "\n"); bw.close(); } catch (IOException e) { logger.error("logBadOperation() failed. ", e); throw new RuntimeException("logBadOperation() failed. ", e); } }
/** * For use in tests * * @param json incoming JSON to parse * @return a node tree * @throws IOException on any parsing problems */ public static ContainerNode parse(String json) throws IOException { ObjectMapper mapper = new ObjectMapper(factory); JsonNode jsonNode = mapper.readTree(json); if (!(jsonNode instanceof ContainerNode)) { throw new IOException("Wrong JSON data: " + json); } return (ContainerNode) jsonNode; }
@Test public void testNestedException() throws Throwable { Exception e = new NoRouteToHostException("that box caught fire 3 years ago"); Exception ioe = new IOException("Datacenter problems", e); ThrowableInformation ti = new ThrowableInformation(ioe); Log4Json l4j = new Log4Json(); long timeStamp = Time.now(); String outcome = l4j.toJson(new StringWriter(), "testNestedException", timeStamp, "INFO", "quoted\"", "new line\n and {}", ti) .toString(); println("testNestedException", outcome); ContainerNode rootNode = Log4Json.parse(outcome); assertEntryEquals(rootNode, Log4Json.LEVEL, "INFO"); assertEntryEquals(rootNode, Log4Json.NAME, "testNestedException"); assertEntryEquals(rootNode, Log4Json.TIME, timeStamp); assertEntryEquals(rootNode, Log4Json.EXCEPTION_CLASS, ioe.getClass().getName()); JsonNode node = assertNodeContains(rootNode, Log4Json.STACK); assertTrue("Not an array: " + node, node.isArray()); node = assertNodeContains(rootNode, Log4Json.DATE); assertTrue("Not a string: " + node, node.isTextual()); //rather than try and make assertions about the format of the text //message equalling another ISO date, this test asserts that the hypen //and colon characters are in the string. String dateText = node.getTextValue(); assertTrue("No '-' in " + dateText, dateText.contains("-")); assertTrue("No '-' in " + dateText, dateText.contains(":")); }
private JsonNode assertNodeContains(ContainerNode rootNode, String key) { JsonNode node = rootNode.get(key); if (node == null) { fail("No entry of name \"" + key + "\" found in " + rootNode.toString()); } return node; }
public Directive(Header header, JsonNode payload, String rawMessage) throws IOException { this.header = header; String namespace = header.getNamespace(); String name = header.getName(); Class<?> payloadType = PayloadConfig.getInstance().findPayloadClass(namespace, name); if (null != payloadType) { this.payload = ObjectMapperUtil.instance().getObjectReader().withType(payloadType).readValue(payload); } else { this.payload = new Payload(); } this.rawMessage = rawMessage; }
@Override public ProducedEventResult deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException { JsonNode node = jp.getCodec().readTree(jp); boolean created = node.get("created").asBoolean(); String reason = null; if (node.has("reason")) { reason = node.get("reason").asText(); } return new ProducedEventResult(created, reason); }
public static JsonNode jsonTree(ObjectMapper m, String json) { try { JsonParser jp = factory.createJsonParser(new StringReader(json)); m.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); return m.readTree(jp); } catch (Exception e) { System.out.println(e); } return NULL_NODE; }
@Override public PollTopicResult deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); JsonNode node = jp.getCodec().readTree(jp); List<TopicRecord> records = new ArrayList<>(); Iterator<JsonNode> it = node.iterator(); while (it.hasNext()) { JsonNode n = it.next(); TopicRecord tr = mapper.readValue(n.toString(), TopicRecord.class); records.add(tr); } return new PollTopicResult(true, records); }
public static JsonNode getJsonNode(JsonNode node, String name) { if (name == null || isNull(node)) return NULL_NODE; StringTokenizer st = new StringTokenizer(name, "."); while (st.hasMoreTokens()) { String key = st.nextToken().trim(); if (key.isEmpty() || null == (node = node.findValue(key))) { return NULL_NODE; } } return node; }
public String search(String query) { try { String url = "?QueryString=" + Utility.urlEncode(query) + "&MaxHits=" + String.valueOf(maxHits); if(queryClass != null) { url += "&QueryClass=" + String.valueOf(queryClass); } HttpGet httpGet = new HttpGet(URL + url); httpGet.addHeader("Accept", "application/json"); HttpResponse response = client.execute(httpGet); // Error Scenario if(response.getStatusLine().getStatusCode() >= 400) { logger.error("Lookup Service could not answer due to: " + response.getStatusLine()); return null; } else { String entities = EntityUtils.toString(response.getEntity()); JsonNode entity = new ObjectMapper().readTree(entities).get("results").get(0); return entity.get("uri").getTextValue(); } } catch (Exception e) { e.printStackTrace(); } return null; }
private String makeRequest(String endpoint, String uri, String requestType) { try { HttpPost httpPost = new HttpPost(endpoint); List<NameValuePair> params = new ArrayList<>(); params.add(new BasicNameValuePair("url", uri)); UrlEncodedFormEntity entity = new UrlEncodedFormEntity(params, Consts.UTF_8); httpPost.setEntity(entity); HttpResponse response = client.execute(httpPost); String result = null; String entities = EntityUtils.toString(response.getEntity()); JsonNode rootNode = new ObjectMapper().readTree(entities).get(requestType); switch (requestType) { case "similarEntities": case "relatedEntities": int count = 0; result = ""; for (JsonNode node : rootNode) { count++; if (count <= ResponseData.MAX_DATA_SIZE) { result += "<" + node.get("url").getTextValue() + "> "; } else { break; } } break; case "summary": result = rootNode.getTextValue(); break; } return result.trim(); } catch (Exception e) { e.printStackTrace(); } return null; }
private JsonNode makeRequest(String url) { try { HttpGet httpGet = new HttpGet(url); httpGet.addHeader("Accept", "application/json"); HttpResponse response = client.execute(httpGet); String entities = EntityUtils.toString(response.getEntity()); return new ObjectMapper().readTree(entities); } catch(Exception e) { e.printStackTrace(); } return null; }
@Override public ReadCommitResult deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException { JsonNode node = jp.getCodec().readTree(jp); boolean created = node.get("created").asBoolean(); String reason = null; if (node.has("reason")) { reason = node.get("reason").asText(); } return new ReadCommitResult(created, reason); }
public JsonNode getUserProfileJson() { if (user == null) { synchronized (lock) { if (user == null) { doLogin(); } } } return user; }
private String getMetricPath(String metricGroupPrefix, Metric metric, JsonNode jsonNode) { String metricName = metric.getLabel() + "(" + jsonNode.path(metric.getXpath()).path("units").asText() + ")"; if(!Strings.isNullOrEmpty(metricGroupPrefix)) { return metricGroupPrefix + "|" + metricName; } else { return metricName; } }
@Override public Value deserialize(JsonNode jsonNode) { MethodValue value=new MethodValue(); value.setArithmetic(JsonUtils.parseComplexArithmetic(jsonNode)); value.setBeanId(JsonUtils.getJsonValue(jsonNode, "beanId")); value.setBeanLabel(JsonUtils.getJsonValue(jsonNode, "beanLabel")); value.setMethodLabel(JsonUtils.getJsonValue(jsonNode, "methodLabel")); value.setMethodName(JsonUtils.getJsonValue(jsonNode, "methodName")); value.setParameters(JsonUtils.parseParameters(jsonNode)); return value; }
@Override public Value deserialize(JsonNode jsonNode) { ConstantValue value=new ConstantValue(); value.setConstantCategory(JsonUtils.getJsonValue(jsonNode, "constantCategory")); value.setConstantLabel(JsonUtils.getJsonValue(jsonNode, "constantLabel")); value.setConstantName(JsonUtils.getJsonValue(jsonNode, "constantName")); value.setArithmetic(JsonUtils.parseComplexArithmetic(jsonNode)); return value; }
@Override public Value deserialize(JsonNode jsonNode) { CommonFunctionValue value=new CommonFunctionValue(); value.setArithmetic(JsonUtils.parseComplexArithmetic(jsonNode)); value.setLabel(JsonUtils.getJsonValue(jsonNode, "label")); value.setName(JsonUtils.getJsonValue(jsonNode, "name")); value.setParameter(JsonUtils.parseCommonFunctionParameter(jsonNode)); value.setValueType(ValueType.CommonFunction); return value; }