Proto Message - Get Field by String (name) - java

I want to get a specific Field from a proto Message with a String, i will try my best to explain what i need to know:
For example we have this .proto File:
message Employee {
string id = 1;
PersonData person_data = 2;
...
}
message PersonData {
string first_name = 1;
string surname = 2;
...
}
Now iam getting a String with a field name like "person_data.first_name".
For example if you want to get the id you must just write:
FieldDescriptor fieldDescriptor = message.getDescriptorForType().findFieldByName("id");
But i need the field "first_name". How can i manage this?
I tried a lot of methods but nothing worked.
Anyone any ideas?

Related

RavenDB query returns null

I'm on RavenDB 3.5.35183. I have a type:
import com.mysema.query.annotations.QueryEntity;
#QueryEntity
public class CountryLayerCount
{
public String countryName;
public int layerCount;
}
and the following query:
private int getCountryLayerCount(String countryName, IDocumentSession currentSession)
{
QCountryLayerCount countryLayerCountSurrogate = QCountryLayerCount.countryLayerCount;
IRavenQueryable<CountryLayerCount> levelDepthQuery = currentSession.query(CountryLayerCount.class, "CountryLayerCount/ByName").where(countryLayerCountSurrogate.countryName.eq(countryName));
CountryLayerCount countryLayerCount = new CountryLayerCount();
try (CloseableIterator<StreamResult<CountryLayerCount>> results = currentSession.advanced().stream(levelDepthQuery))
{
while(results.hasNext())
{
StreamResult<CountryLayerCount> srclc = results.next();
System.out.println(srclc.getKey());
CountryLayerCount clc = srclc.getDocument();
countryLayerCount = clc;
break;
}
}
catch(Exception e)
{
}
return countryLayerCount.layerCount;
}
The query executes successfully, and shows the correct ID for the document I'm retrieving (e.g. "CountryLayerCount/123"), but its data members are both null. The where clause also works fine, the country name is used to retrieve individual countries. This is so simple, but I can't see where I've gone wrong. The StreamResult contains the correct key, but getDocument() doesn't work - or, rather, it doesn't contain an object. The collection has string IDs.
In the db logger, I can see the request coming in:
Receive Request # 29: GET - geodata - http://localhost:8888/databases/geodata/streams/query/CountryLayerCount/ByName?&query=CountryName:Germany
Request # 29: GET - 22 ms - geodata - 200 - http://localhost:8888/databases/geodata/streams/query/CountryLayerCount/ByName?&query=CountryName:Germany
which, when plugged into the browser, correctly gives me:
{"Results":[{"countryName":"Germany","layerCount":5,"#metadata":{"Raven-Entity-Name":"CountryLayerCounts","Raven-Clr-Type":"DbUtilityFunctions.CountryLayerCount, DbUtilityFunctions","#id":"CountryLayerCounts/212","Temp-Index-Score":0.0,"Last-Modified":"2018-02-03T09:41:36.3165473Z","Raven-Last-Modified":"2018-02-03T09:41:36.3165473","#etag":"01000000-0000-008B-0000-0000000000D7","SerializedSizeOnDisk":164}}
]}
The index definition:
from country in docs.CountryLayerCounts
select new {
CountryName = country.countryName
}
AFAIK, one doesn't have to index all the fields of the object to retrieve it in its entirety, right ? In other words, I just need to index the field(s) to find the object, not all the fields I want to retrieve; at least that was my understanding...
Thanks !
The problem is related to incorrect casing.
For example:
try (IDocumentSession sesion = store.openSession()) {
CountryLayerCount c1 = new CountryLayerCount();
c1.layerCount = 5;
c1.countryName = "Germany";
sesion.store(c1);
sesion.saveChanges();
}
Is saved as:
{
"LayerCount": 5,
"CountryName": "Germany"
}
Please notice we use upper case letters in json for property names (this only applies to 3.X versions).
So in order to make it work, please update json properties names + edit your index:
from country in docs.CountryLayerCounts
select new {
CountryName = country.CountryName
}
Btw. If you have per country aggregation, then you can simply query using:
QCountryLayerCount countryLayerCountSurrogate =
QCountryLayerCount.countryLayerCount;
CountryLayerCount levelDepthQuery = currentSession
.query(CountryLayerCount.class, "CountryLayerCount/ByName")
.where(countryLayerCountSurrogate.countryName.eq(countryName))
.single();

Group values from a parameter list in a loop according to the prefix of the parameter

I am fetching a param list from my jsp which I need to identify according to the prefix so that I can set the values in my entity class.
The parameter names looks like the below:
List<String> reqParamNames = Arrays.asList("1_component_role", "2_component_role", "3_component_role",
"4_component_role", "1_survey_wt", "2_survey_wt", "3_survey_wt", "4_survey_wt", "1dynaGroup1", "1component_role1", "1wt1", "2dynaGroup1", "2component_role1", "2wt1", "3dynaGroup1",
"3component_role1", "3wt1", "4dynaGroup1", "4component_role1", "4wt1");
Now, from the above list, I need to get the param according to the prefix, i.e.1,2,3,4 etc. Once grouped correctly, I would need to set it to my Entity class so that I can save the parameters in my table using Hibernate.
I am unable to set the values for the dynamic table.
#RequestMapping(value = { "dynamicSettings/persist" }, method = RequestMethod.POST)
public String saveComponents(HttpServletRequest request, HttpServletResponse response,
Model model) {
LOG.debug("Entering persist area :: ");
Locale locale = LocaleUtil.getLocale();
// ToDo: validation for form
//For dynamic tables
List<String> reqParamNames = (List<String>) Collections.list((Enumeration<String>)request.getParameterNames());
for(int i =0; i < reqParamNames.size(); i++){
System.out.println("Param names are {} ::"+ reqParamNames.get(i));
String paramName = reqParamNames.get(i);
Matcher m = Pattern.compile("[^0-9]*([0-9]+).*").matcher(paramName);
if (m.matches()) {
System.out.println("Number ::" +m.group(1)); // Need to comment/remove this post development
}
System.out.println("ParamNumber ::" +""+m.group(1));
String attributeValue = request.getParameter(paramName);
System.out.println("Param Name ::"+paramName+"::: Attribute value ::"+attributeValue);
DynamicComponentSettings dynamicSettings = new DynamicComponentSettings();
if( i == paramNumber){
String group_type = request.getParameter("groupType"+i);
String component_role = request.getParameter("component_role"+i);
String survey_weight = request.getParameter("wt"+i);
System.out.println("Group Type ::"+group_type+ "::Component Role::" +component_role+ "::Survey Weight::"+survey_weight);
if(!StringUtils.isEmpty(group_type) && StringUtils.isEmpty(component_role)&&!StringUtils.isEmpty(survey_weight)){
Double survey_wt = Double.parseDouble(survey_weight);
dynamicSettings.setSurvey_wt(survey_wt);
dynamicSettings.setGroup_type(group_type);
dynamicSettings.setComponent_role(component_role);
}
}
dynamicComponentService.saveDynamicComponents(dynamicSettings);
}
**//For concrete table**
List<DynamicComponentSettings> resultList = dynamicComponentService.loadAllDynamicComponents();
for(DynamicComponentSettings component : resultList)
{
String _survey_wt = request.getParameter(component.getPk1().toString() + "survey_wt");
String _groupRoleType = request.getParameter(component.getPk1().toString() + "group_type");
String _componentRole = request.getParameter(component.getPk1().toString() + "component_role");
if(!StringUtils.isEmpty(_survey_wt) && StringUtils.isEmpty(_groupRoleType)&&!StringUtils.isEmpty(_componentRole)){
Double survey_wt = Double.parseDouble(_survey_wt);
component.setSurvey_wt(survey_wt);
component.setGroup_type(_groupRoleType);
component.setComponent_role(_componentRole);
}
dynamicComponentService.saveDynamicComponents(component);
}
return "redirect:" + "some url";
}
The concrete table works correctly, i.e. saving values correctly.
Entity class
<package declaration>
<imports>
#Entity
#Table(name = "dynamic_components")
public class DynamicComponentSettings {
/** The pk1. */
#Id
#SequenceGenerator(name = "dynamic_components_seq", sequenceName = "dynamic_components_seq", allocationSize = 1)
#GeneratedValue(strategy = GenerationType.AUTO, generator = "dynamic_components_seq")
private Long pk1;
private String group_type;
private String component_role;
private Double survey_wt;
<getters and setters>
}
Please provide your inputs and provide guidance as how to save the dynamic table values.
I managed to figure out the problems and fix it. There are multiple problems in that code sample. For eg. the loops are incorrect, the approach to match with the main loop was horribly wrong.
I had to get the prefix and suffix for each item, loop correctly[i.e. first get the suffix and prefix of the table and then based on suffix match, iterate through the prefix like rows] and put each dynamic table data with suffix being the key and prefix+data+suffix being the values into a Map containing linked lists. After that, I had to loop again through the Map containing the lists to set the values to my entity class correctly.
Please pardon me for not posting the code again as the method is quite long and may not be of much help. In any case, if someone does want to see how this was solved, please let me know.
Thanks for your time.

"Generic" Parameters on model (Java)

In C # I could use (on data-annotations) this code below without problems:
[RegularExpression(#"^myRegex$", ErrorMessage = "The field {0} is not in the correct format.")]
public string Name { get; set; }
But in Java it doesn't work, I tried it:
#Pattern(regexp = "^myRegex$", message = "The field {0} is not in the correct format.")
private String name;
The {0} just return {0}, not the "name" field.
So, could someone help me with some example in Java to make it work?

How to Bind a Model to a SWT Text but showing only one field in the text

I have a Remote File Model which has fields as file name, file path, and connection IP,connection port etc for the remote directory.I want to show only the file path in a Text.
I am using JFace Data binding for binding the model to SWT Text but I am able to bind only 1 field to it.
Please help me to bind the Complete model to the Text and showing only one field.
Also tell me if it is possible or not or there is some other way.
If I understand you correctly you want to show multiple model fields in one SWT Text widget? You can do it in the following way:
class FileModel {
private String name;
private String filePath;
private String ip;
// other fields, getters and setters
public String getFileSummary() {
return name + " : " + filePath + " : " + ip;
}
public void setFileSummary(String summary) {
// ignore
}
}
Then you can bind it like this:
FileModel model;
new DataBindingContext().bindValue(SWTObservables.observeText(text, SWT.Modify),
BeansObservables.observeValue(model, "fileSummary"), new UpdateValueStrategy(), new UpdateValueStrategy());
The idea is that while specifying "fileSummary" field name to bind in your model, JFace will look for getter and setter for that field, so you don't actually need a field itself.
In getter you can provided required info and you could even parse some special format in setter and assign those to related fields, something like this:
public void setFileSummary(String summary) {
// todo: implement in a smart way;)
String[] parts = summary.split(" : ");
name = parts[0];
filePath = parts[1];
ip = parts[2];
}

how use protocol buffers?

I watched a lot of tutorials, but I can not understand how to use protocol buffers
Why "message User "? why not "class User "? and how Eclipse has created such a message?
and why name = 2 ? not name = "Max"
ption java_outer_classname="ProtoUser";
message User {
required int32 id = 1; // DB record ID
required string name = 2;
required string firstname = 3;
required string lastname = 4;
required string ssn= 5;
// Embedded Address message spec
message Address {
required int32 id = 1;
required string country = 2 [default = "US"];;
optional string state = 3;
optional string city = 4;
optional string street = 5;
optional string zip = 6;
enum Type {
HOME = 0;
WORK = 1;
}
optional Type addrType = 7 [default = HOME];
}
repeated Address addr = 16;
}
Why "message User "? why not "class User "?
Google Protocol Buffers (GPB) does not have class in its syntax, it has message instead.
https://developers.google.com/protocol-buffers/docs/style
This file is just text file, it should have .proto extension. After all you will run a utility on it which would generate real Java classes which you can import and easily use in your project.
https://developers.google.com/protocol-buffers/docs/javatutorial
Compiling Your Protocol Buffers
protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto
required string lastname = 4;
4 stands for the field id, not a value, it is going to be used to generate a bit stream.
Protobuffer use message(keyword) instead of class
Inside the class you define the structure of. schema.
For example
message Person{
string name = 1;
repeated string id = 2;
Type phoneType = 3;
}
enum Type{
CellPhone = 0;
HomePhone = 1;
}
In the above example, we are defining the structure of the Person Message.
It has name which datatype is a string, id which is an array of the string and type(when you expect only certain values then use an enum. In this case, we assume that phoneNumber can be either CellPhone or HomePhone. If someone is sending any other value then IT will through UNKNOWN proto value exception)
required: means parameter is required
To use proto first create proto classes using mvn clean install
Then create protobuilder
Protobuilder to set for above proto
Person person = Person.newBuilder().setName("testName")
.setPhoneType(Type.CellPhone)
.addAllId(listIds)
.build;
Once you set the value you can not change it. If you want to change the value then you need to create another proto.
Pesron person1 = Person.newBuilder(person).setName("ChangeName").build;
person1 will have the name ChangeName, phoneType CellPhone, and ids arrays of strings.
More information: https://developers.google.com/protocol-buffers

Categories

Resources