I have nested schemas imported in a WSDL file, I need to extract the Schema names but I am able to do it only till one level, not the nested schemas.Please help
Map mp = new HashMap();
for( Object o : def.getTypes().getExtensibilityElements()) {
if( o instanceof javax.wsdl.extensions.schema.Schema ) {
// org.w3c.dom.Element elt = ((javax.wsdl.extensions.schema.SchemaImport) o) //.getElement();
Schema sc = (javax.wsdl.extensions.schema.Schema) o;
mp.put(sc.getElement().getNamespaceURI(),sc);
mp.putAll(sc.getImports());
System.out.println(mp);
//++i;
}
}
Got the solution on the net, sharing the same as it works for me:
for( Object o : def.getTypes().getExtensibilityElements()) {
if( o instanceof javax.wsdl.extensions.schema.Schema ) {
Schema sc = (javax.wsdl.extensions.schema.Schema) o;
mp.put(sc.getElement().getNamespaceURI(),sc);
mp.putAll(sc.getImports());
readPackagesFromImports(sc);
System.out.println(mp);
}
}
And here goes the readPackagesFromImports method:
private static ArrayList<String> readPackagesFromImports(Schema schema) throws SchemaReaderException{
ArrayList<String> schemaImportPkgList = new ArrayList<String>();
Map map = schema.getImports();
Collection collection = map.values();
for(Iterator i =collection.iterator(); i.hasNext(); ){
Vector value = (Vector) i.next();
for(Object vectorObj:value){
SchemaImport si = (SchemaImport)vectorObj;
System.out.println("Reading import for SchemaLocation ="+si.getSchemaLocationURI());
Schema refSchema = si.getReferencedSchema();
//Implementing recursion for reading import within import
//First read inline schema for imported schema
ArrayList<String> inlineSchemaPkgList = readPackagesFromInlineSchema(refSchema);
for(String packageString:inlineSchemaPkgList){
if(packageString!=null){
schemaImportPkgList.add(packageString);
}
}
//Lets read if import has any imports by recurisvely calling readPackageFromImport again....
ArrayList<String> rec_ImportPkgList = readPackagesFromImports(refSchema);
for(String packageString:rec_ImportPkgList){
if(packageString!=null){
schemaImportPkgList.add(packageString);
}
}
}
}
return schemaImportPkgList;
}
Related
Our program displays a tree control showing the metadata structure of the XML file they are using as a datasource. So it displays all elements & attributes in use in the XML file, like this:
Employees
Employee
FirstName
LastName
Orders
Order
OrderId
For the case where the user does not pass us a XSD file, we need to walk the XML file and build up the metadata structure.
The full code for this is at SaxonQuestions.zip, TestBuildTree.java and is also listed below.
I am concerned that my code is not the most efficient, or maybe even wrong. It works, but it works on the 3 XML files I tested it on. My questions are:
What is the best way to get the root element from the DOM? Is it walking the children of the DOM root node?
What is the best way to determine if an element has data (as opposed to just child elements)? The best I could come up with throws an exception if not and I don't think code executing the happy path should throw an exception.
What is the best way to get the class of the data held in an element or attribute? Is it: ((XdmAtomicValue)((XdmNode)currentNode).getTypedValue()).getValue().getClass();
Is the best way to walk all the nodes to use XdmNode.axisIterator? And to do so as I have in this code?
TestBuildTree.java
import net.sf.saxon.s9api.*;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
public class TestBuildTree {
public static void main(String[] args) throws Exception {
XmlDatasource datasource = new XmlDatasource(
new FileInputStream(new File("files", "SouthWind.xml").getCanonicalPath()),
null);
// Question:
// Is this the best way to get the root element?
// get the root element
XdmNode rootNode = null;
for (XdmNode node : datasource.getXmlRootNode().children()) {
if (node.getNodeKind() == XdmNodeKind.ELEMENT) {
rootNode = node;
break;
}
}
TestBuildTree buildTree = new TestBuildTree(rootNode);
Element root = buildTree.addNode();
System.out.println("Schema:");
printElement("", root);
}
private static void printElement(String indent, Element element) {
System.out.println(indent + "<" + element.name + "> (" + (element.type == null ? "null" : element.type.getSimpleName()) + ")");
indent += " ";
for (Attribute attr : element.attributes)
System.out.println(indent + "=" + attr.name + " (" + (attr.type == null ? "null" : attr.type.getSimpleName()) + ")");
for (Element child : element.children)
printElement(indent, child);
}
protected XdmItem currentNode;
public TestBuildTree(XdmItem currentNode) {
this.currentNode = currentNode;
}
private Element addNode() throws SaxonApiException {
String name = ((XdmNode)currentNode).getNodeName().getLocalName();
// Question:
// Is this the best way to determine that this element has data (as opposed to child elements)?
Boolean elementHasData;
try {
((XdmNode) currentNode).getTypedValue();
elementHasData = true;
} catch (Exception ex) {
elementHasData = false;
}
// Questions:
// Is this the best way to get the type of the element value?
// If no schema is it always String?
Class valueClass = ! elementHasData ? null : ((XdmAtomicValue)((XdmNode)currentNode).getTypedValue()).getValue().getClass();
Element element = new Element(name, valueClass, null);
// add in attributes
XdmSequenceIterator currentSequence;
if ((currentSequence = moveTo(Axis.ATTRIBUTE)) != null) {
do {
name = ((XdmNode) currentNode).getNodeName().getLocalName();
// Questions:
// Is this the best way to get the type of the attribute value?
// If no schema is it always String?
valueClass = ((XdmAtomicValue)((XdmNode)currentNode).getTypedValue()).getValue().getClass();
Attribute attr = new Attribute(name, valueClass, null);
element.attributes.add(attr);
} while (moveToNextInCurrentSequence(currentSequence));
moveTo(Axis.PARENT);
}
// add in children elements
if ((currentSequence = moveTo(Axis.CHILD)) != null) {
do {
Element child = addNode();
// if we don't have this, add it
Element existing = element.getChildByName(child.name);
if (existing == null)
element.children.add(child);
else
// add in any children this does not have
existing.addNewItems (child);
} while (moveToNextInCurrentSequence(currentSequence));
moveTo(Axis.PARENT);
}
return element;
}
// moves to element or attribute
private XdmSequenceIterator moveTo(Axis axis) {
XdmSequenceIterator en = ((XdmNode) currentNode).axisIterator(axis);
boolean gotIt = false;
while (en.hasNext()) {
currentNode = en.next();
if (((XdmNode) currentNode).getNodeKind() == XdmNodeKind.ELEMENT || ((XdmNode) currentNode).getNodeKind() == XdmNodeKind.ATTRIBUTE) {
gotIt = true;
break;
}
}
if (gotIt) {
if (axis == Axis.ATTRIBUTE || axis == Axis.CHILD || axis == Axis.NAMESPACE)
return en;
return null;
}
return null;
}
// moves to next element or attribute
private Boolean moveToNextInCurrentSequence(XdmSequenceIterator currentSequence)
{
if (currentSequence == null)
return false;
while (currentSequence.hasNext())
{
currentNode = currentSequence.next();
if (((XdmNode)currentNode).getNodeKind() == XdmNodeKind.ELEMENT || ((XdmNode)currentNode).getNodeKind() == XdmNodeKind.ATTRIBUTE)
return true;
}
return false;
}
static class Node {
String name;
Class type;
String description;
public Node(String name, Class type, String description) {
this.name = name;
this.type = type;
this.description = description;
}
}
static class Element extends Node {
List<Element> children;
List<Attribute> attributes;
public Element(String name, Class type, String description) {
super(name, type, description);
children = new ArrayList<>();
attributes = new ArrayList<>();
}
public Element getChildByName(String name) {
for (Element child : children) {
if (child.name.equals(name))
return child;
}
return null;
}
public void addNewItems(Element child) {
for (Attribute attrAdd : child.attributes) {
boolean haveIt = false;
for (Attribute attrExist : attributes)
if (attrExist.name.equals(attrAdd.name)) {
haveIt = true;
break;
}
if (!haveIt)
attributes.add(attrAdd);
}
for (Element elemAdd : child.children) {
Element exist = null;
for (Element elemExist : children)
if (elemExist.name.equals(elemAdd.name)) {
exist = elemExist;
break;
}
if (exist == null)
children.add(elemAdd);
else
exist.addNewItems(elemAdd);
}
}
}
static class Attribute extends Node {
public Attribute(String name, Class type, String description) {
super(name, type, description);
}
}
}
XmlDatasource.java
import com.saxonica.config.EnterpriseConfiguration;
import com.saxonica.ee.s9api.SchemaValidatorImpl;
import net.sf.saxon.Configuration;
import net.sf.saxon.lib.FeatureKeys;
import net.sf.saxon.s9api.*;
import net.sf.saxon.type.SchemaException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamSource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
public class XmlDatasource {
/** the DOM all searches are against */
private XdmNode xmlRootNode;
private XPathCompiler xPathCompiler;
/** key == the prefix; value == the uri mapped to that prefix */
private HashMap<String, String> prefixToUriMap = new HashMap<>();
/** key == the uri mapped to that prefix; value == the prefix */
private HashMap<String, String> uriToPrefixMap = new HashMap<>();
public XmlDatasource (InputStream xmlData, InputStream schemaFile) throws SAXException, SchemaException, SaxonApiException, IOException {
boolean haveSchema = schemaFile != null;
// call this before any instantiation of Saxon classes.
Configuration config = createEnterpriseConfiguration();
if (haveSchema) {
Source schemaSource = new StreamSource(schemaFile);
config.addSchemaSource(schemaSource);
}
Processor processor = new Processor(config);
DocumentBuilder doc_builder = processor.newDocumentBuilder();
XMLReader reader = createXMLReader();
InputSource xmlSource = new InputSource(xmlData);
SAXSource saxSource = new SAXSource(reader, xmlSource);
if (haveSchema) {
SchemaValidator validator = new SchemaValidatorImpl(processor);
doc_builder.setSchemaValidator(validator);
}
xmlRootNode = doc_builder.build(saxSource);
xPathCompiler = processor.newXPathCompiler();
if (haveSchema)
xPathCompiler.setSchemaAware(true);
declareNameSpaces();
}
public XdmNode getXmlRootNode() {
return xmlRootNode;
}
public XPathCompiler getxPathCompiler() {
return xPathCompiler;
}
/**
* Create a XMLReader set to disallow XXE aattacks.
* #return a safe XMLReader.
*/
public static XMLReader createXMLReader() throws SAXException {
XMLReader reader = XMLReaderFactory.createXMLReader();
// stop XXE https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#JAXP_DocumentBuilderFactory.2C_SAXParserFactory_and_DOM4J
reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
reader.setFeature("http://xml.org/sax/features/external-general-entities", false);
reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
return reader;
}
private void declareNameSpaces() throws SaxonApiException {
// saxon has some of their functions set up with this.
prefixToUriMap.put("saxon", "http://saxon.sf.net");
uriToPrefixMap.put("http://saxon.sf.net", "saxon");
XdmValue list = xPathCompiler.evaluate("//namespace::*", xmlRootNode);
if (list == null || list.size() == 0)
return;
for (int index=0; index<list.size(); index++) {
XdmNode node = (XdmNode) list.itemAt(index);
String prefix = node.getNodeName() == null ? "" : node.getNodeName().getLocalName();
// xml, xsd, & xsi are XML structure ones, not ones used in the XML
if (prefix.equals("xml") || prefix.equals("xsd") || prefix.equals("xsi"))
continue;
// use default prefix if prefix is empty.
if (prefix == null || prefix.isEmpty())
prefix = "def";
// this returns repeats, so if a repeat, go on to next.
if (prefixToUriMap.containsKey(prefix))
continue;
String uri = node.getStringValue();
if (uri != null && !uri.isEmpty()) {
xPathCompiler.declareNamespace(prefix, uri);
prefixToUriMap.put(prefix, uri);
uriToPrefixMap.put(uri, prefix); }
}
}
public static EnterpriseConfiguration createEnterpriseConfiguration()
{
EnterpriseConfiguration configuration = new EnterpriseConfiguration();
configuration.supplyLicenseKey(new BufferedReader(new java.io.StringReader(deobfuscate(key))));
configuration.setConfigurationProperty(FeatureKeys.SUPPRESS_XPATH_WARNINGS, Boolean.TRUE);
return configuration;
}
}
I would like to know how I can return the node names instead of the node IDs in the Java console.
The following output is shown in the console:
The desired output should look like:
Just without all the information but only with the Node names (which equal Airportnames).
My Java code looks like the following:
package com.routesNeo4j;
import org.neo4j.driver.v1.*;
import java.util.ArrayList;
import java.util.List;
/**
* Created by e on 11.06.17.
*/
public class Neo4JRouting implements AutoCloseable, Neo4J_Connector {
static Driver driver;
public Neo4JRouting(String startAirport, String destinationAirport, StatementResult shortestPath) {
driver = GraphDatabase.driver("bolt://ec2-13-58-101-13.us-east-2.compute.amazonaws.com:7687",
AuthTokens.basic("neo4j", "Einloggen_123"));
try(Session session = driver.session()) {
shortestPath = session.run("MATCH (a:" + startAirport.toLowerCase() + "), (b:" + destinationAirport.toLowerCase()
+ "), p = allShortestPaths((a)-[r*1..4]-(b)) UNWIND rels(p) AS rel RETURN nodes(p), sum(rel.weight) " +
"AS weight ORDER BY sum(rel.weight)");
List<Record> storeList = storeList(shortestPath);
while (shortestPath.hasNext()) {
System.out.println(shortestPath.next().toString());
}
System.out.println(storeList);
} catch (Exception e) {
e.printStackTrace();
}
}
public List<Record> storeList(StatementResult statementResult) {
List<Record> list = new ArrayList<>();
while (statementResult.hasNext()) {
list.add(statementResult.next());
}
return list;
}
#Override
public Driver runDriver(String user, AuthToken basicAuthToken) throws Exception {
return null;
}
#Override
public void close() throws Exception {
}
}
I am looking forward to your answers. Many thanks!
Every row you are returning contains a list of nodes and a weight. That's what you ask in your query and that's what you get. So you have to "unpack" that result into the format that you desire.
Couple of code-snippets to show what I mean :
StatementResult vResult = vSession.run(aCypher);
while (vResult.hasNext()) {
Record vRecord = vResult.next();
vMutator.pushNode("row");
for (Pair <String, Value> vListEntry : vRecord.fields()) {
process_listentry(vSession, vMutator, vListEntry.key(), vListEntry.value());
}
vMutator.popNode(); // row
}
and then in process_listentry :
private void process_listentry(Session vSession, IHDSMutator vMutator, String vKey, Value vValue) {
...
else if (vValue.type().equals(vSession.typeSystem().NODE())){
vMutator.pushNode(vKey);
vMutator.addNode("_id", Long.toString(vValue.asNode().id()));
for (String lLabel : vValue.asNode().labels()) {
vMutator.addNode("_label", lLabel);
}
for (String lKey : vValue.asNode().keys()) {
Value lValue = vValue.asNode().get(lKey);
process_listentry(vSession, vMutator, lKey, lValue);
}
vMutator.popNode();
}
...
but it does depend on what you ask in the query and thus have to unpack ...
Hope this helps,
Tom
im trying to make a miniJava parser but im having trouble figuring out a way to parse method declarations that have no formal parameters.
e.g public int getNumber()
The code that i have right now works for parameters of one or more, but im not sure how to return an empty formal object as clearly the problem lies with the line returning null.
Is there a way to skip the return statement altogether and return nothing?
public Formal nt_FormalList() :
{
Type t;
Token s;
LinkedList<Formal> fl = new LinkedList<Formal>();
Formal f;
}
{
t = nt_Type() s = <IDENTIFIER> (f = nt_FormalRest() {fl.add(f);})*
{ return new Formal(t, s.image); }
| {}
{ return null; }
}
.....
public class Formal {
public final Type t;
public final String i;
public Formal(Type at, String ai) {
t = at;
i = ai;
}
I'd suggest that you return list of Formals from nt_FormalList.
public List<Formal> nt_FormalList() :
{
LinkedList<Formal> fl = new LinkedList<Formal>();
Formal f;
}
{
[ f = nt_Formal() {fl.add(f);}
(<COMMA> f = nt_Formal() {fl.add(f);})*
]
{ return fl; }
}
I am a novice in android and I am using achartEngine library to draw line Graph. what I want to do is to update the graph by using a spinner. For exmaple, if I chose the first option I will get a yellow graph and when
I swich to the second option in my spinner, the graph changes and becomes white with new title and data
for the moment I can only update the data but not the rest of the graph
package com.example.test2;
import java.text.Format;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.SeriesSelection;
import org.achartengine.model.TimeSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import org.apache.http.NameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.example.test2.R;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
public class Graphique extends Activity {
private GraphicalView mChart1;
private GraphicalView mChart2;
private TimeSeries glecimieSeries ;
private TimeSeries pressionSeries;
private XYMultipleSeriesDataset dataset;
private XYSeriesRenderer glecimieRenderer;
private XYSeriesRenderer pressionRenderer;
private XYMultipleSeriesRenderer multiRenderer;
// Progress Dialog
private ProgressDialog pDialog;
// Creating JSON Parser object
JSONParser jParser = new JSONParser();
ArrayList<HashMap<String, String>> listeappareil;
// url to get all products list
private static String url_liste_appareil ;
// JSON Node names
private static final String TAG_SUCCESS = "success";
private static String TAG_APPAREIL;
private static final String TAG_PID = "pid";
private static final String TAG_NOM = "nom";
private static final String TAG_J = "jour";
private static final String TAG_Y = "Y";
// products JSONArray
JSONArray appareil = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.graphique);
// getting intent data
Intent in = getIntent();
// Get JSON values from previous intent
String pid = in.getStringExtra(TAG_PID);
String nom = in.getStringExtra(TAG_NOM);
// Displaying all values on the screen
TextView lblNom = (TextView) findViewById(R.id.nom_patient);
lblNom.setText(nom);
Spinner mySpinner = (Spinner)findViewById(R.id.mesure);
ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.appareils, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mySpinner.setAdapter(adapter);
OnItemSelectedListener selectedGraph = new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> spinner, View container,
int position, long id) {
String graph = spinner.getItemAtPosition(position).toString().toLowerCase();
if(graph == "tensiometre"){
url_liste_appareil = "http://10.0.2.2/connexion_android/"+graph+".php";
TAG_APPAREIL = graph;
// Setting up chart
setupChart2();
// Start plotting chart
new ChartTask2().execute();
}else{
url_liste_appareil = "http://10.0.2.2/connexion_android/"+graph+".php";
TAG_APPAREIL = graph;
// Setting up chart
setupChart1();
// Start plotting chart
new ChartTask1().execute();
}
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
};
// Setting ItemClick Handler for Spinner Widget
mySpinner.setOnItemSelectedListener(selectedGraph);
}
private void setupChart1(){
// Creating TimeSeries for Glecimie
glecimieSeries = new TimeSeries("Glecimie");
// Creating a dataset to hold each series
dataset = new XYMultipleSeriesDataset();
// Adding Glecimie Series to the dataset
dataset.addSeries(glecimieSeries);
// Creating XYSeriesRenderer to customize glecimieSeries
glecimieRenderer = new XYSeriesRenderer();
glecimieRenderer.setColor(Color.YELLOW);
glecimieRenderer.setPointStyle(PointStyle.CIRCLE);
glecimieRenderer.setFillPoints(true);
glecimieRenderer.setLineWidth(2);
glecimieRenderer.setDisplayChartValues(true);
// Creating a XYMultipleSeriesRenderer to customize the whole chart
multiRenderer = new XYMultipleSeriesRenderer();
multiRenderer.setZoomButtonsVisible(true);
// Adding glecimieRenderer and pressionRenderer to multipleRenderer
// Note: The order of adding dataseries to dataset and renderers to multipleRenderer
// should be same
multiRenderer.addSeriesRenderer(glecimieRenderer);
// Getting a reference to LinearLayout of the MainActivity Layout
LinearLayout chartContainer = (LinearLayout) findViewById(R.id.chart_container);
// Creating a Time Chart
mChart1 = (GraphicalView) ChartFactory.getTimeChartView(getBaseContext(), dataset, multiRenderer,"dd-MMM-yyyy");
multiRenderer.setClickEnabled(true);
multiRenderer.setSelectableBuffer(10);
// Setting a click event listener for the graph
mChart1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Format formatter = new SimpleDateFormat("dd-MMM-yyyy");
SeriesSelection seriesSelection = mChart1.getCurrentSeriesAndPoint();
if (seriesSelection != null) {
int seriesIndex = seriesSelection.getSeriesIndex();
String selectedSeries="Glecimie";
if(seriesIndex==0)
selectedSeries = "Glecimie";
else
selectedSeries = "Pression";
// Getting the clicked Date ( x value )
long clickedDateSeconds = (long) seriesSelection.getXValue();
Date clickedDate = new Date(clickedDateSeconds);
String strDate = formatter.format(clickedDate);
// Getting the y value
int amount = (int) seriesSelection.getValue();
// Displaying Toast Message
Toast.makeText(
getBaseContext(),
"Prélèvement au " + strDate + " : " + amount ,
Toast.LENGTH_SHORT).show();
}
}
});
chartContainer.removeAllViews();
// Adding the Line Chart to the LinearLayout
chartContainer.addView(mChart1);
}
private class ChartTask1 extends AsyncTask<String, String, String>{
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(Graphique.this);
pDialog.setMessage("Loading data. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
// Generates dummy data in a non-ui thread
protected String doInBackground(String... params) {
// Building Parameters
List<NameValuePair> param = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_liste_appareil, "GET", param);
// Check your log cat for JSON reponse
Log.d("Tous les appareil: ", json.toString());
try{
// Checking for SUCCESS TAG
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// products found
// Getting Array of Products
appareil = json.getJSONArray(TAG_APPAREIL);
Date[] dt = new Date[appareil.length()];
// looping through All Products
for (int j = 0; j < appareil.length(); j++) {
JSONObject p = appareil.getJSONObject(j);
// Storing each json item in variable
GregorianCalendar gc = new GregorianCalendar(2012, 10, j+1);
dt[j] = gc.getTime();
String y = p.getString(TAG_Y);
String jr = p.getString(TAG_J);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(jr);
// Adding data to Glecimie and Pression Series
glecimieSeries.add(d,Double.parseDouble(y));
multiRenderer.setXTitle("Dates");
multiRenderer.setYTitle("Prélèvements");
}
}
}catch (JSONException e) {
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// Plotting generated data in the graph
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into the graph
* */
mChart1.repaint();
}
});
}
}
private void setupChart2(){
// Creating TimeSeries for Pression
pressionSeries = new TimeSeries("Pression");
// Creating a dataset to hold each series
dataset = new XYMultipleSeriesDataset();
// Adding Glecimie Series to dataset
dataset.addSeries(pressionSeries);
// Creating XYSeriesRenderer to customize pressionSeries
pressionRenderer = new XYSeriesRenderer();
pressionRenderer.setColor(Color.YELLOW);
pressionRenderer.setPointStyle(PointStyle.CIRCLE);
pressionRenderer.setFillPoints(true);
pressionRenderer.setLineWidth(2);
pressionRenderer.setDisplayChartValues(true);
// Creating a XYMultipleSeriesRenderer to customize the whole chart
multiRenderer = new XYMultipleSeriesRenderer();
multiRenderer.setZoomButtonsVisible(true);
// Adding glecimieRenderer and pressionRenderer to multipleRenderer
// Note: The order of adding dataseries to dataset and renderers to multipleRenderer
// should be same
multiRenderer.addSeriesRenderer(pressionRenderer);
// Getting a reference to LinearLayout of the MainActivity Layout
LinearLayout chartContainer = (LinearLayout) findViewById(R.id.chart_container);
// Creating a Time Chart
mChart2 = (GraphicalView) ChartFactory.getTimeChartView(getBaseContext(), dataset, multiRenderer,"dd-MMM-yyyy");
multiRenderer.setClickEnabled(true);
multiRenderer.setSelectableBuffer(10);
// Setting a click event listener for the graph
mChart2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Format formatter = new SimpleDateFormat("dd-MMM-yyyy");
SeriesSelection seriesSelection = mChart2.getCurrentSeriesAndPoint();
if (seriesSelection != null) {
int seriesIndex = seriesSelection.getSeriesIndex();
String selectedSeries="Glecimie";
if(seriesIndex==0)
selectedSeries = "Glecimie";
else
selectedSeries = "Pression";
// Getting the clicked Date ( x value )
long clickedDateSeconds = (long) seriesSelection.getXValue();
Date clickedDate = new Date(clickedDateSeconds);
String strDate = formatter.format(clickedDate);
// Getting the y value
int amount = (int) seriesSelection.getValue();
// Displaying Toast Message
Toast.makeText(
getBaseContext(),
" Prélèvement au" + strDate + " : " + amount ,
Toast.LENGTH_SHORT).show();
}
}
});
chartContainer.removeAllViews();
// Adding the Line Chart to the LinearLayout
chartContainer.addView(mChart2);
}
private class ChartTask2 extends AsyncTask<String, String, String>{
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(Graphique.this);
pDialog.setMessage("Loading data. Please wait...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
// Generates dummy data in a non-ui thread
protected String doInBackground(String... params) {
// Building Parameters
List<NameValuePair> param = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_liste_appareil, "GET", param);
// Check your log cat for JSON reponse
Log.d("Tous les appareil: ", json.toString());
try{
// Checking for SUCCESS TAG
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
// products found
// Getting Array of Products
appareil = json.getJSONArray(TAG_APPAREIL);
Date[] dt = new Date[appareil.length()];
// looping through All Products
for (int j = 0; j < appareil.length(); j++) {
JSONObject p = appareil.getJSONObject(j);
// Storing each json item in variable
GregorianCalendar gc = new GregorianCalendar(2012, 10, j+1);
dt[j] = gc.getTime();
String y = p.getString(TAG_Y);
String jr = p.getString(TAG_J);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(jr);
// Adding data to Glecimie and Pression Series
pressionSeries.add(d,Double.parseDouble(y));
multiRenderer.setChartTitle("la pression");
multiRenderer.setXTitle("Dates");
multiRenderer.setYTitle("Prélèvements");
}
}
}catch (JSONException e) {
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
// Plotting generated data in the graph
protected void onPostExecute(String file_url) {
// dismiss the dialog after getting all products
pDialog.dismiss();
// updating UI from Background Thread
runOnUiThread(new Runnable() {
public void run() {
/**
* Updating parsed JSON data into the graph
* */
mChart2.repaint();
}
});
}
}
// Initiating Menu XML file (menu.xml)
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_graphique, menu);
return (super.onCreateOptionsMenu(menu));
}
}
Please help
In order to refresh both charts, you need to call repaint on both:
mChart1.repaint();
mChart2.repaint();
You can update the color and other values of the chart by passing values.
In openChart() method you can pass the values.
private void openChart(final String[] code, final int[] distribution,final int color){
defaultRenderer.setBackgroundColor(color);
}
I have the following issue:
a drop down with a list of elements
each of these elements has a fixed key, which is used by the IChoiceRenderer implementation to look up the localized version of the key (it's a standard, utility renderer implemented in a different package)
the list of localized keys is in a properties file, linked to the panel which instantiates the dropdown.
Is there an elegant/reusable solution to have the dropdown display its elements sorted alphabetically ?
In the end, I think using the render is probably the best approach. To make it reusable and efficient, I isolated this in a Behavior.
Here's the code:
import org.apache.wicket.Component;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.html.form.AbstractChoice;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import static java.util.Arrays.sort;
/**
* This {#link Behavior} can only be used on {#link AbstractChoice} subclasses. It will sort the choices
* according to their "natural display order" (i.e. the natural order of the display values of the choices).
* This assumes that the display value implements {#link Comparable}. If this is not the case, you should
* provide a comparator for the display value. An instance of this class <em>cannot be shared</em> between components.
* Because the rendering can be costly, the sort-computation is done only once, by default,
* unless you set to <code>false</code> the <code>sortOnlyOnce</code> argument in the constructor.
*
* #author donckels (created on 2012-06-07)
*/
#SuppressWarnings({"unchecked"})
public class OrderedChoiceBehavior extends Behavior {
// ----- instance fields -----
private Comparator displayValueComparator;
private boolean sortOnlyOnce = true;
private boolean sorted;
// ----- constructors -----
public OrderedChoiceBehavior() {
}
public OrderedChoiceBehavior(boolean sortOnlyOnce) {
this.sortOnlyOnce = sortOnlyOnce;
}
public OrderedChoiceBehavior(boolean sortOnlyOnce, Comparator displayValueComparator) {
this.sortOnlyOnce = sortOnlyOnce;
this.displayValueComparator = displayValueComparator;
}
// ----- public methods -----
#Override
public void beforeRender(Component component) {
if (this.sorted && this.sortOnlyOnce) { return;}
AbstractChoice owner = (AbstractChoice) component;
IChoiceRenderer choiceRenderer = owner.getChoiceRenderer();
List choices = owner.getChoices();
// Temporary data structure: store the actual rendered value with its initial index
Object[][] displayValuesWithIndex = new Object[choices.size()][2];
for (int i = 0, valuesSize = choices.size(); i < valuesSize; i++) {
Object value = choices.get(i);
displayValuesWithIndex[i][0] = choiceRenderer.getDisplayValue(value);
displayValuesWithIndex[i][1] = i;
}
sort(displayValuesWithIndex, new DisplayValueWithIndexComparator());
List valuesCopy = new ArrayList(choices);
for (int i = 0, length = displayValuesWithIndex.length; i < length; i++) {
Object[] displayValueWithIndex = displayValuesWithIndex[i];
int originalIndex = (Integer) displayValueWithIndex[1];
choices.set(i, valuesCopy.get(originalIndex));
}
this.sorted = true;
}
public Comparator getDisplayValueComparator() {
return this.displayValueComparator;
}
// ----- inner classes -----
private class DisplayValueWithIndexComparator implements Comparator<Object[]> {
// ----- Comparator -----
public int compare(Object[] left, Object[] right) {
Object leftDisplayValue = left[0];
Object rightDisplayValue = right[0];
if (null == leftDisplayValue) { return -1;}
if (null == rightDisplayValue) { return 1;}
if (null == getDisplayValueComparator()) {
return ((Comparable) leftDisplayValue).compareTo(rightDisplayValue);
} else {
return getDisplayValueComparator().compare(leftDisplayValue, rightDisplayValue);
}
}
}
}
Use this extension of DropDownChoice using Java's Collator (basically locale sensitive sorting - take national characters and national sorting rules into account)
Code tested with Wicket 6 and Java 5+:
import java.text.Collator;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import org.apache.wicket.Session;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.model.IModel;
import com.google.common.collect.Ordering;
/**
* DropDownChoice which sort its choices (or in HTML's terminology select's options) according it's localized value
* and using current locale based Collator so it's sorted how it should be in particular language (ie. including national characters,
* using right order).
*
* #author Michal Bernhard michal#bernhard.cz 2013
*
* #param <T>
*/
public class OrderedDropDownChoice<T> extends DropDownChoice<T> {
public OrderedDropDownChoice(String id, IModel<? extends List<? extends T>> choices, IChoiceRenderer<? super T> renderer) {
super(id, choices, renderer);
}
public OrderedDropDownChoice(String id, IModel<? extends List<? extends T>> choices) {
super(id, choices);
}
public OrderedDropDownChoice(String id) {
super(id);
}
public OrderedDropDownChoice(
String id,
IModel<T> model,
IModel<? extends List<? extends T>> choices,
IChoiceRenderer<? super T> renderer) {
super(id, model, choices, renderer);
}
#Override
public List<? extends T> getChoices() {
List<? extends T> unsortedChoices = super.getChoices();
List<? extends T> sortedChoices = Ordering.from(displayValueAlphabeticComparator()).sortedCopy(unsortedChoices);
return sortedChoices;
}
private Collator localeBasedTertiaryCollator() {
Locale currentLocale = Session.get().getLocale();
Collator collator = Collator.getInstance(currentLocale);
collator.setStrength(Collator.TERTIARY);
return collator;
}
private Comparator<T> displayValueAlphabeticComparator() {
final IChoiceRenderer<? super T> renderer = getChoiceRenderer();
return new Comparator<T>() {
#Override
public int compare(T o1, T o2) {
Object o1DisplayValue = renderer.getDisplayValue(o1);
Object o2DisplayValue = renderer.getDisplayValue(o2);
return localeBasedTertiaryCollator().compare(o1DisplayValue, o2DisplayValue);
}
};
}
}
Copied from https://gist.github.com/michalbcz/7236242
If you want a Wicket-based solution you can try to sort the list with something like that:
public class ChoiceRendererComparator<T> implements Comparator<T> {
private final IChoiceRenderer<T> renderer;
public ChoiceRendererComparator(IChoiceRenderer<T> renderer) {
this.renderer = renderer;
}
#SuppressWarnings("unchecked")
public int compare(T o1, T o2) {
return ((Comparable<Object>) renderer.getDisplayValue(o1)).compareTo(renderer.getDisplayValue(o2));
}
}
Usage:
List<Entity> list = ...
IChoiceRenderer<Entity> renderer = ...
Collections.sort(list, new ChoiceRendererComparator<Entity>(renderer));
DropDownChoice<Entity> dropdown = new DropDownChoice<Entity>("dropdown", list, renderer);
The solution we use at my company is Javascript based, we set a special css class on the dropdowns we want to be sorted, and a little jQuery trick does the sort.
Facing the same problem, I moved part of the localisation data from my XMLs to the database, implemented a matching Resolver and was able to use the localized Strings for sorting.
The table design and hibernate configuration was kind of tricky and is described here: Hibernate #ElementCollection - Better solution needed.
The ResourceLoader is along these lines:
public class DataBaseStringResourceLoader extends ComponentStringResourceLoader {
private static final transient Logger logger = Logger
.getLogger(DataBaseStringResourceLoader.class);
#Inject
private ISomeDAO someDao;
#Inject
private IOtherDao otherDao;
#Inject
private IThisDAO thisDao;
#Inject
private IThatDAO thatDao;
#Override
public String loadStringResource(Class<?> clazz, String key, Locale locale,
String style, String variation) {
String resource = loadFromDB(key, new Locale(locale.getLanguage()));
if (resource == null) {
resource = super.loadStringResource(clazz, key, locale, style, variation);
}
return resource;
}
private String loadFromDB(String key, Locale locale) {
String resource = null;
if (locale.getLanguage() != Locale.GERMAN.getLanguage()
&& locale.getLanguage() != Locale.ENGLISH.getLanguage()) {
locale = Locale.ENGLISH;
}
if (key.startsWith("some") || key.startsWith("other")
|| key.startsWith("this") || key.startsWith("that")) {
Integer id = Integer.valueOf(key.substring(key.indexOf(".") + 1));
ILocalizedObject master;
if (key.startsWith("some")) {
master = someDao.findById(id);
} else if (key.startsWith("other")) {
master = otherDao.findById(id);
} else if (key.startsWith("this") ){
master = thisDao.findById(id);
} else {
master = thatDao.findById(id);
}
if (master != null && master.getNames().get(locale) != null) {
resource = master.getNames().get(locale).getName();
} else if (master == null) {
logger.debug("For key " + key + " there is no master.");
}
}
return resource;
}
[...]
}