RallyRestAPI querying ScopedAttributeDefinition types - java

Using the RallyRestAPI, is there a way to query ScopedAttributeDefinition types? This appears to define custom datatypes in Rally. I am trying to build a data dictionary of the custom types we use in Rally and associate these custom types to the object they are attributes of. (In case that doesn't make sense, here's an example: We have a custom field called Enabler Lead on Rally PortfolioItems. I'd like to query Rally for all custom fields for PortfolioItem and get the Enabler Field, and its metadata, from the Rally REST API.)
I'm using the Java client.

I filed a github issue to add support for the ScopedAttributeDefinition: https://github.com/RallyTools/RallyRestToolkitForJava/issues/19
In the meantime though you can work around it by using the underlying http client directly. This code queries for all projects in your workspace and then finds the type definition for Portfolio Item and then for each project grabs all the custom attribute defs via the scopedattributedefinition endpoint and prints out their hidden/required status.
QueryRequest projectQuery = new QueryRequest("project");
projectQuery.setLimit(Integer.MAX_VALUE);
QueryResponse projectResponse = restApi.query(projectQuery);
QueryRequest typeDefQuery = new QueryRequest("typedefinition");
typeDefQuery.setQueryFilter(new QueryFilter("Name", "=", "Portfolio Item"));
QueryResponse typeDefResponse = restApi.query(typeDefQuery);
JsonObject piTypeDef = typeDefResponse.getResults().get(0).getAsJsonObject();
for(JsonElement projectResult : projectResponse.getResults()) {
JsonObject project = projectResult.getAsJsonObject();
System.out.println("Project: " + project.get("Name").getAsString());
//Begin hackery (note we're not handling multiple pages-
// if you have more than 200 custom attributes you'll have to page
String scopedAttributeDefUrl = "/project/" + project.get("ObjectID").getAsLong() +
"/typedefinition/" + piTypeDef.get("ObjectID").getAsLong() + "/scopedattributedefinition" +
"?fetch=Hidden,Required,Name&query=" + URLEncoder.encode("(Custom = true)", "utf-8");
String attributes = restApi.getClient().doGet(scopedAttributeDefUrl);
QueryResponse attributeResponse = new QueryResponse(attributes);
//End hackery
for(JsonElement customAttributeResult : attributeResponse.getResults()) {
JsonObject customAttribute = customAttributeResult.getAsJsonObject();
System.out.print("\tAttribute: " + customAttribute.get("Name").getAsString());
System.out.print(", Hidden: " + customAttribute.get("Hidden").getAsBoolean());
System.out.println(", Required: " + customAttribute.get("Required").getAsBoolean());
}
System.out.println();
}
Any other info you'd like for each of those custom fields should be accessible just by querying the Attributes collection from the piTypeDef.

Related

How to show customized JSON in Swagger UI?

I'm using springfox-boot-starter 3.0 to build my API documents.
All things are going in a right way except one case. There seems to be no way to show a JSON example in Swagger UI model if my request parameter is a Map or JSONObject like this:
#PostMapping("/trigger")
#ApiOperation(value = "trigger something")
#ApiImplicitParams(
#ApiImplicitParam(name = "reqForm",
value = "{\"123123\":\"123123\"}", example = "{\"123123\":\"123123\"}"))
public StandardResult trigger(#RequestBody Map reqForm) throws Exception {
Object dagId = reqForm.get("dagId");
Object conf = reqForm.get("conf");
return StandardResult.succeed(dagService.trigger(dagId, conf));
}
I just want to show an example value and a example model of the JSON in Swagger UI and I don't want to write any of extra .java file to define the structure.
Other controllers with plenty of .java files to describe structure can be shown in Swagger UI like this:
But in this case, the Map shall be a dynamic parameter which would change frequently. So I hope to show a model of that JSON without too many .java files so that others who are reading my document would have a nice experience and I will not have to change .java file every day.
I know how to show the model and examples in Swagger UI by creating multiple Java beans using #ApiModel and #ApiModelProperty. But that may also lead to a dozens of .java files in order to create only one JSON and it is hard to find and update a property while something in JSON was changed.
For example, I'm going to tell others to send a JSON like this:
"dagInfo": {
"id": 17,
"tags": [
"test",
"task",
"dag"
],
"interval": "None",
"dagName": "testDagGenerate",
"dagCode": "test_dag_generate",
"dagDescription": "test"
}
by using #ApiImplicitParams shown below, I can show the example value but no model in Swagger UI.
#PostMapping("/trigger")
#ApiOperation(value = "trigger something")
#ApiImplicitParams(
#ApiImplicitParam(name = "reqForm",
value = "example json", example = "\"dagInfo\": {\n" +
" \"id\": 17,\n" +
" \"tags\": [\n" +
" \"test\",\n" +
" \"task\",\n" +
" \"dag\"\n" +
" ],\n" +
" \"interval\": \"None\",\n" +
" \"dagName\": \"testDagGenerate\",\n" +
" \"dagCode\": \"test_dag_generate\",\n" +
" \"dagDescription\": \"test\"\n" +
" }"))
public StandardResult trigger(#RequestBody JSONObject reqForm) throws Exception {
Long dagId = reqForm.getObject("dagId", Long.class);
JSONObject conf = reqForm.getJSONObject("conf");
return StandardResult.succeed(dagService.trigger(dagId, conf));
}
I have no idea how to write this model of example JSON directly to Swagger.
Or there is no way to define a example model in Swagger UI without any configuration?
The dependency of Maven is shown below:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>

Using ELKI with Mongodb

Using test cases I was able to see how ELKI can be used directly from Java but now I want to read my data from MongoDB and then use ELKI to cluster geographic (long, lat) data.
I can only cluster data from a CSV file using ELKI. Is it possible to connect de.lmu.ifi.dbs.elki.database.Database with MongoDB? I can see from the java debugger that there is a databaseconnection field in de.lmu.ifi.dbs.elki.database.Database.
I query MongoDB creating POJO for each row and now I want to cluster these objects using ELKI.
It is possible to read data from MongoDB and write it in a CSV file then use ELKI to read that CSV file but I would like to know if there is a simpler solution.
---------FINDINGS_1:
From ELKI - Use List<String> of objects to populate the Database I found that I need to implement de.lmu.ifi.dbs.elki.datasource.DatabaseConnection and specifically override the loadData() method which returns an instance of MultiObjectsBundle.
So I think I should wrap a list of POJO with MultiObjectsBundle. Now i'm looking at the MultiObjectsBundle and it looks like the data should be held in columns. Why columns datatype is List> shouldnt it be List? just a list of items you want to cluster?
I'm a little confused. How is ELKI going to know that it should look at the long and lat for POJO? Where do I tell ELKI to do this? Using de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation?
---------FINDINGS_2:
I have tried to use ArrayAdapterDatabaseConnection and I have tried implementing DatabaseConnection. Sorry I need thing in very simple terms for me to understand.
This is my code for clustering:
int minPts=3;
double eps=0.08;
double[][] data1 = {{-0.197574246, 51.49960695}, {-0.084605692, 51.52128377}, {-0.120973687, 51.53005939}, {-0.156876, 51.49313},
{-0.144228881, 51.51811784}, {-0.1680743, 51.53430039}, {-0.170134484,51.52834133}, { -0.096440751, 51.5073853},
{-0.092754157, 51.50597426}, {-0.122502346, 51.52395143}, {-0.136039674, 51.51991453}, {-0.123616824, 51.52994371},
{-0.127854211, 51.51772703}, {-0.125979294, 51.52635795}, {-0.109006325, 51.5216612}, {-0.12221963, 51.51477076}, {-0.131161087, 51.52505093} };
// ArrayAdapterDatabaseConnection dbcon = new ArrayAdapterDatabaseConnection(data1);
DatabaseConnection dbcon = new MyDBConnection();
ListParameterization params = new ListParameterization();
params.addParameter(de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN.Parameterizer.MINPTS_ID, minPts);
params.addParameter(de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN.Parameterizer.EPSILON_ID, eps);
params.addParameter(DBSCAN.DISTANCE_FUNCTION_ID, EuclideanDistanceFunction.class);
params.addParameter(AbstractDatabase.Parameterizer.DATABASE_CONNECTION_ID, dbcon);
params.addParameter(AbstractDatabase.Parameterizer.INDEX_ID,
RStarTreeFactory.class);
params.addParameter(RStarTreeFactory.Parameterizer.BULK_SPLIT_ID,
SortTileRecursiveBulkSplit.class);
params.addParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 1000);
Database db = ClassGenericsUtil.parameterizeOrAbort(StaticArrayDatabase.class, params);
db.initialize();
GeneralizedDBSCAN dbscan = ClassGenericsUtil.parameterizeOrAbort(GeneralizedDBSCAN.class, params);
Relation<DoubleVector> rel = db.getRelation(TypeUtil.DOUBLE_VECTOR_FIELD);
Relation<ExternalID> relID = db.getRelation(TypeUtil.EXTERNALID);
DBIDRange ids = (DBIDRange) rel.getDBIDs();
Clustering<Model> result = dbscan.run(db);
int i =0;
for(Cluster<Model> clu : result.getAllClusters()) {
System.out.println("#" + i + ": " + clu.getNameAutomatic());
System.out.println("Size: " + clu.size());
System.out.print("Objects: ");
for(DBIDIter it = clu.getIDs().iter(); it.valid(); it.advance()) {
DoubleVector v = rel.get(it);
ExternalID exID = relID.get(it);
System.out.print("DoubleVec: ["+v+"]");
System.out.print("ExID: ["+exID+"]");
final int offset = ids.getOffset(it);
System.out.print(" " + offset);
}
System.out.println();
++i;
}
The ArrayAdapterDatabaseConnection produces two clusters, I just had to play around with the value of epsilon, when I set epsilon=0.008 dbscan started creating clusters. When i set epsilon=0.04 all the items were in 1 cluster.
I have also tried to implement DatabaseConnection:
#Override
public MultipleObjectsBundle loadData() {
MultipleObjectsBundle bundle = new MultipleObjectsBundle();
List<Station> stations = getStations();
List<DoubleVector> vecs = new ArrayList<DoubleVector>();
List<ExternalID> ids = new ArrayList<ExternalID>();
for (Station s : stations){
String strID = Integer.toString(s.getId());
ExternalID i = new ExternalID(strID);
ids.add(i);
double[] st = {s.getLongitude(), s.getLatitude()};
DoubleVector dv = new DoubleVector(st);
vecs.add(dv);
}
SimpleTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<>(DoubleVector.FACTORY, 2, 2, DoubleVector.FACTORY.getDefaultSerializer());
bundle.appendColumn(type, vecs);
bundle.appendColumn(TypeUtil.EXTERNALID, ids);
return bundle;
}
These long/lat are associated with an ID and I need to link them back to this ID to the values. Is the only way to go that using the ID offset (in the code above)? I have tried to add ExternalID column but I don't know how to retrieve the ExternalID for a particular NumberVector?
Also after seeing Using ELKI's Distance Function I tried to use Elki's longLatDistance but it doesn't work and I could not find any examples to implement it.
The interface for data sources is called DatabaseConnection.
JavaDoc of DatabaseConnection
You can implement a MongoDB-based interface to get the data.
It is not complicated interface, it has a single method.

BIRT report parameter with multiple values passed from JSP page

I have integrated BIRT in web application.I am using Eclipse Luna,JDK 1.8, BIRT Report Engine 4.1.1 and Data source I am using is Excel Data Source(not JDBC and all that). From my JSP page I am passing two parameters in the URL using Javascript AJAX like:`
var reporturl ="/Reporting/loadReport?ReportName="+reportName+"&ReportFormat=html&Supplier=Supplier4&Metal=Gold&Metal=Tin";
$("#reportData").html("Loading...<br><img src='/Reporting/resources/images/loading.gif' align='middle' >");
$('#reportData').load(reporturl ,function(response, status, xhr) {
if (status == "error") {
var msg = "Sorry but there was an error getting details ! ";
$("#reportData").html(msg + xhr.status + " " + xhr.statusText);
}
});
For report parameter "Metal" I have selected Display type : List Box, Data Type : String and have selected Dynamic Values and then have checked "Allow Multiple Values" checkbox. Then in the Property Editor of table, in Filters tab I have given the expressions as follows:
row["Supplier Name"] Equal to params["Supplier"].value
row["Metal"] In params["Metal"].value
After this switching to JavaEE perspective in my ReportRenderer.java , I have the following code to get multiple values associated with the "Metal" parameter(which are passed from the URL), I have merged those values as a comma(,) seperated list in a single String variable like :
public static String getParameter( HttpServletRequest request,
String parameterName )
{
if ( request.getCharacterEncoding( ) == null )
{
try
{
request.setCharacterEncoding( UTF_8_ENCODE );
}
catch ( UnsupportedEncodingException e )
{
}
}
String[] values = request.getParameterValues(parameterName);
String temp="";
if(values.length>1)
{
int i=0;
for(i=0;i<values.length-1;i++)
{
temp=temp+values[i]+",";
}
temp=temp+values[i];
}
else
{
temp = values[0];
}
return temp;
}
In a HashMap I am getting all parameters and it's respective values successfully and have set that Map like:
HashMap<String,Object> tempMap = new HashMap<String,Object>();
tempMap = discoverAndSetParameters( runnable, request );
for(String str : tempMap.keySet())
{
System.out.println("Key : "+str);
System.out.println("Value : "+tempMap.get(str));
}
iRunTask.setParameterValues(tempMap);
Here runnable is the object of IReportRunnable and request is the object of HttpServletRequest.
Now when I am running the web application, after clicking on the hyperlink named "Reports" I am getting following exception on console and no output on web page.
org.eclipse.birt.report.engine.api.impl.ParameterValidationException: The type of parameter "Metal" is expected as "Object[]", not "java.lang.String".
at org.eclipse.birt.report.engine.api.impl.EngineTask.validateAbstractScalarParameter(EngineTask.java:857)
at org.eclipse.birt.report.engine.api.impl.EngineTask.access$0(EngineTask.java:789)
at org.eclipse.birt.report.engine.api.impl.EngineTask$ParameterValidationVisitor.visitScalarParameter(EngineTask.java:706)
at org.eclipse.birt.report.engine.api.impl.EngineTask$ParameterVisitor.visit(EngineTask.java:1531)
at org.eclipse.birt.report.engine.api.impl.EngineTask.doValidateParameters(EngineTask.java:692)
at org.eclipse.birt.report.engine.api.impl.RunTask.doRun(RunTask.java:214)
at org.eclipse.birt.report.engine.api.impl.RunTask.run(RunTask.java:86)
Please help me how to resolve this problem and again I am specifying I am using Excel Data Source not JDBC or Scripted and all that. I have already gone through many blogs where questions are related to JDBC data source and that didn't helped me.
When a listbox parameter is declared as "Allow multiple values", the BIRT engine is expecting an array of values, but in your case you send a String.
Therefore when you detect a multi-value parameter, instead of building a comma-separated String you should build a java array of values and pass this array to the parameter map. This way it will work.
Take care elements of this array should have the datatype expected by BIRT: if "Metal" parameter is set as "String" type in your report-design then you shoud be able to use "values" array as it is from getParameter function, otherwise it would be necessary to build a fresh array.

Bing Search API error using odata4j

I am trying to run Bing search API. I used odata4j and tried the code provided here:
How to use Bing search api in Java
ODataConsumer c = ODataConsumers
.newBuilder("https://api.datamarket.azure.com/Bing/Search")
.setClientBehaviors(OClientBehaviors.basicAuth("accountKey", "{your account key here}"))
.build();
OQueryRequest<OEntity> oRequest = c.getEntities("Web")
.custom("Query", "stackoverflow bing api");
Enumerable<OEntity> entities = oRequest.execute();
After I registered in the bing service, I obtained the key and placed it inside the double quotation in the above code. I got the following error:
Exception in thread "main" java.lang.RuntimeException: Expected status OK, found Bad Request. Server response:
Parameter: Query is not of type String
at org.odata4j.jersey.consumer.ODataJerseyClient.doRequest(ODataJerseyClient.java:165)
at org.odata4j.consumer.AbstractODataClient.getEntities(AbstractODataClient.java:69)
at org.odata4j.consumer.ConsumerQueryEntitiesRequest.doRequest(ConsumerQueryEntitiesRequest.java:59)
at org.odata4j.consumer.ConsumerQueryEntitiesRequest.getEntries(ConsumerQueryEntitiesRequest.java:50)
at org.odata4j.consumer.ConsumerQueryEntitiesRequest.execute(ConsumerQueryEntitiesRequest.java:40)
at BingAPI.main(BingAPI.java:20)
Caused by: org.odata4j.exceptions.UnsupportedMediaTypeException: Unknown content type text/plain;charset=utf-8
at org.odata4j.format.FormatParserFactory.getParser(FormatParserFactory.java:78)
at org.odata4j.jersey.consumer.ODataJerseyClient.doRequest(ODataJerseyClient.java:161)
... 5 more
I could not figure out the problem.
All what you need is to set your query like that %27stackoverflow bing api%27
Here is my source code:
ODataConsumer consumer = ODataConsumers
.newBuilder("https://api.datamarket.azure.com/Bing/Search/v1/")
.setClientBehaviors(
OClientBehaviors.basicAuth("accountKey",
"{My Account ID}"))
.build();
System.out.println(consumer.getServiceRootUri() + consumer.toString());
OQueryRequest<OEntity> oQueryRequest = consumer.getEntities("Web")
.custom("Query", "%27stackoverflow%27");
System.out.println("oRequest : " + oQueryRequest);
Enumerable<OEntity> entities = oQueryRequest.execute();
System.out.println(entities.elementAt(0));
You can further try different queries with different filters by keep adding name-value pairs by using .custom("Type of parameter","parameter") of the oQueryrequest object.Say you want to search for indian food but you want only small square images.
ODataConsumer consumer = ODataConsumers
.newBuilder("https://api.datamarket.azure.com/Bing/Search/v1/")
.setClientBehaviors(
OClientBehaviors.basicAuth("accountKey",
"YOUR ACCOUNT KEY"))
.build();
System.out.println(consumer.getServiceRootUri() + consumer.toString());
OQueryRequest<OEntity> oQueryRequest = consumer.getEntities("Image")
.custom("Query", "%27indian food%27");
oQueryRequest.custom("Adult", "%27Moderate%27");
oQueryRequest.custom("ImageFilters", "%27Size:Small+Aspect:Square%27");
System.out.println("oRequest : " + oQueryRequest);
Enumerable<OEntity> entities = oQueryRequest.execute();
int count = 0;
Iterator<OEntity> iter = entities.iterator();
System.out.println(iter.next());

Java ArrayList into Name value pair

In a java class, am using an arraylist say reports containing list of all the reports which have reportid, reportname, reporttype etc which i want to add into NameValuePair and send a Http postmethod call to a particular url.
I want to add the arraylists - reportname into name value pair(org.apache.commons.httpclient.NameValuePair) and then use the http client post method to submit the name value pair data to a particular url.
Here is my name value pair
if (validateRequest()) {
NameValuePair[] data = {
new NameValuePair("first_name", firstName),
new NameValuePair("last_name", lastName),
new NameValuePair("email", mvrUser.getEmail()),
new NameValuePair("organization", mvrUser.getOrganization()),
new NameValuePair("phone", mvrUser.getPhone()),
new NameValuePair("website", mvrUser.getWebsite()),
new NameValuePair("city", mvrUser.getCity()),
new NameValuePair("state", mvrUser.getState()),
new NameValuePair("country", mvrUser.getCountry()),
new NameValuePair(**"report(s)", reports**.)
};
please suggest me how to add the reports arraylist reportname into reports field of NameValuePair.
--
thanks
# adarsh
can I use with generics something like this?
reportname = "";
for (GSReport report : reports) {
reportname = reportname + report.getReportName();
reportname += ",";
}
and then add in namevalue pair as
new NameValuePair("report(s)", reportname)
for name value pair use map like things... eg. Hastable(it is synchronized) , u can use other
implementation of Map which are not synchronized.
I suggest to serialize your reports ArrayList into a JSON formatted String.
new NameValuePair("reports", reportsAsJson)
You can build your reportsAsJson variable using any of the JSON serialization libraries (like the one at http://json.org/java/). It will have approximatively this format :
reportsAsJson = "[{reportid:'1',reportname:'First Report',reporttype:'Type 1'}, {reportid:'2',reportname:'Seond Report',reporttype:'Type 2'}]";
Well, you cannot do that. NameValuePair takes in String arguments in the constructor. It makes sense as it is used for HTTP POST.
What you can do is come up with a way to serialize the Report object into String and send this string as a string parameter. One way of doing this maybe is to delimit the parameters of the Report class.
reports=reportName1|reportName2|reportName3
Assuming reports is your ArrayList,
String reportsStr = "";
for(int i = 0; i < reports.size(); i++) {
reportStr += reportName;
if(i != reports.size() - 1) {
reportsStr += "|";
}
}
NameValuePair nvPair = new NameValuePair("reports", reportsStr);

Categories