Add metadata to fields in proto3 for Java - grpc

Proto3 has been simplified such that the required and optional fields are no longer supported (See Why required and optional is removed in Protocol Buffers 3). Is there still a way to label a certain field as required?
I've looked into FieldOptions, and tried something like this:
message MyMeta {
bool isRequired = 1;
}
extend google.protobuf.FieldOptions {
MyMeta meta = 1234;
}
message Person {
string name = 1 [ (meta) = { isRequired: true }];
string address = 2 [ (meta) = { isRequired: true }];
string remarks = 3;
}
After compiling it into Java code, and as I was checking the compiled Java code I don't see any link between the fields and its metadata I specified in proto. Did I miss something here?

After a bit of tinkering and using #Eric Anderson's idea on using proto reflection, here is a way to retrieve MyMeta from the Person.name field:
Descriptor rootDesc = PersonProto.getDescriptor();
FieldDescriptor name = rootDesc.findFieldByName("name");
FieldDescriptor ext = rootDesc.getFile().getExtensions().get(0);
MyMeta meta = (MyMeta) name.getOptions().getField(ext);
boolean isReq = meta.getIsRequired();

No, that functionality was removed; use documentation instead. If you are trying to use FieldOptions for your own extensions, then you can make your own protoc plugin to generate supplemental code (like a verify utility) or use proto reflection at runtime (via FooMessage.getDescriptor() and Descriptors.FieldDescriptor.getOptions() in Java).

Related

Not able to get organization form node in alfresco

Using Alfresco Community 5.0.d and not able to get organization from node.
File: pickerresults.lib.js
Method: createPersonResult(node)
function createPersonResult(node)
{
var personObject =
{
typeShort: node.typeShort,
isContainer: false,
properties: {},
displayPath: node.displayPath,
nodeRef: "" + node.nodeRef
}
// define properties for person
personObject.properties.userName = node.properties.userName;
// defining new property for the personObject but
// but not getting any value
personObject.properties.companyname = (node.properties["cm:organization"] ? node.properties["cm:organization"] : "");
personObject.properties.companyname = (node.properties.organization ? node.properties.organization : "");
return personObject;
}
Override the pickerresults.lib.js file by copying it to location as below.
/Applications/alfresco-5.0.d/tomcat/shared/classes/alfresco/extension/templates/webscripts/org/alfresco/repository/forms/pickerresults.lib.js
how could I get organization name?
also how could I debug the node properties like logger.log is there but does not work here.
Thanks.
please try to get properties without extra "." in
node.properties.["cm:organization"]
like:
node.properties["cm:organization"]
please refer this doc link
http://docs.alfresco.com/4.0/references/API-JS-ScriptNode.html
properties
Provides access to all the properties of this node. The properties returned are accessed via an associative array. Properties of a node can be accessed in the following ways:
Example: node.properties["name"]
Example: node.properties.name
example i have tried:
var node =people.getPerson("admin");
logger.log(node.properties["cm:email"]);
logger.log(node.properties.email);

Setting a static (constant) POST parameter with netflix feign

I'm using a REST api that requires a few fields to be set. My application should always set some of the fields to the same value. Is it possible to make those values "hard coded" in the interface with the feign definition (or somewhere else)?
My feign declaration looks like the example. Let's say I always want to use the same agent from this application. Is that doable?
#RequestLine("POST /files")
#Headers("Content-Type: application/json")
default FileMetadata addFile(#Param("file_name") String fileName,
#Param("agent") String agent,
#Param("md5") String md5,
#Param("file_type") String fileType) {
return new FileMetadata.Builder().build();
}
You have different alternatives, in the case you are using the Spring Annotations you could use defaultValue annotation property to determine the default value
#RequestParam(value = "agent", required = false, defaultValue = "AnyAgent") String agent
But in the case you are using the netflix-feign annotations, and seems it is what you are doing, you would need to add in the path, i.e. in the #RequestLine annotation:
static final String DEFAULT_VALUE_AGENT = "agent";
#RequestLine("POST /files?agent=" + DEFAULT_VALUE_AGENT)
....
But if you are refering to Body POST, you could do it using annotation #Body:
#RequestLine("POST /files")
#Body("%7B\"file_name\": \"{user_name}\", \"agent\": \"" + DEFAULT_VALUE_AGENT +"\"%7D") //... other params..
....
Edit
Based on the Github repository documentation, if you are using Java 8, you could do a default method which calls the other method with a param constant. Just like next
#RequestLine("POST /files")
#Headers("Content-Type: application/json")
FileMetadata addFile(#Param("file_name") String fileName,
#Param("agent") String agent,
#Param("md5") String md5,
#Param("file_type") String fileType);
#RequestLine("POST /files")
#Headers("Content-Type: application/json")
default FileMetadata addFileConstant(#Param("file_name") String fileName,
#Param("md5") String md5,
#Param("file_type") String fileType) {
addFile(fileName, "constant_value", md5, fileType);
}
Personally, I think is more flexible than the other options I proposed before. And the idea works in POST Body as well if they are params.
I had the same situation.
The problem is solved as follows:
added this to the main api on the server that I was knocking on (i.e., on the receiving side, and not on the sending side request).
for example:
#RequestParam(value = "code", required = false, defaultValue = "AAA") String code
Required is required = false (instead of required = true).

SDL Tridion 2011: Dynamically fill or add a metadata field using a C# TBB

Is it possible to set the value of a metadata field dynamically from a TBB? Or is it possible to dynamically add a metadata field that does not necessarily exist on a schema from a TBB?
The reason I want to do this is that I am using DD4T and I want to have the breadcrumb automatically added into the DD4T xml.
I have tried the following:
public override void Transform(Engine engine, Package package)
{
Initialize(engine,package);
var page = GetPage();
string output = page.OrganizationalItem.Title;
var parent = page.OrganizationalItem as StructureGroup;
while (parent != null)
{
output = GetLinkToStructureGroupIndexPage(parent) + Separator + output;
parent = parent.OrganizationalItem as StructureGroup;
}
// I tried this to dynamically add the field
//var metadata = page.Metadata.OwnerDocument.CreateElement("breadcrumb");
//metadata.InnerText = output;
//page.Metadata.AppendChild(metadata);
//I tried this to dynamically set an existing field on the schema
foreach (XmlNode xml in page.Metadata)
{
Log.Debug("Metadata field:" +xml.Name);
if(xml.Name == "breadcrumb")
{
xml.InnerText = output;
}
}
package.PushItem(Package.PageName, package.CreateTridionItem(ContentType.Page, page));
}
However, neither of these methods seem to work. Is this impossible?
DD4T has utility class FieldsBuilder with AddFields method where you can inject additional metadata. DD4T has a TBB which does update component metadata from Folder Metadata and it is called InheritMetadataComponent.
You could take a look at this here and you could implement the same:
http://code.google.com/p/dynamic-delivery-4-tridion/source/browse/trunk/dotnet/DD4T.Templates/InheritMetadataComponent.cs
FieldsBuilder.AddFields(component.MetadataFields, tcmFields, 1, false, mergeAction, Manager);
The easiest approach is to create a template class which implements DD4T.Templates.Base.BasePageTemplate. In that class, you implement the method TransformPage, which takes a DD4T page as its argument. You can access the 'TCM page' using the method GetTcmPage().
Example:
using TCM = Tridion.ContentManager.CommunicationManagement;
using Dynamic = DD4T.ContentModel;
public class MyTemplate : BasePageTemplate
{
protected override void TransformPage(Dynamic.Page page)
{
TCM.Page tcmPage = GetTcmPage();
string breadCrumbs = GetBreadCrumbs (tcmPage); // TODO: implement GetBreadCrumbs
Field f = new Field();
f.Name = "breadCrumbs";
f.FieldType = FieldType.Text;
f.Values.Add(breadCrumbs);
page.MetadataFields.Add("breadCrumbs", f);
}
}
page.MetadataFields.Add(name, field); should work if your template extends the DD4T.Templates.Base.BasePageTemplate
You can also take a look at the source of the Add inherited metadata to page TBB in DD4T, that also shows a way of adding Metadata which gets published to the broker.

Get type of metadata fields of a Metadata schema

I want to get the all fields along with type/datatype of the metadata fields of a Metadata schema.
I have written below sample code to achieve the functionality and I am able to get Name, Description etc but could not find any property with type/dataType. If anyone of you have any idea, please suggest...
var client = new SessionAwareCoreService2010Client();
client.ClientCredentials.Windows.ClientCredential.UserName = "myUserName";
client.ClientCredentials.Windows.ClientCredential.Password = "myPassword";
client.Open();
if (client.State == System.ServiceModel.CommunicationState.Opened)
{
var schemaUri = "tcm:1-47-8";
var fields= client.ReadSchemaFields(schemaUri, true, new ReadOptions());
var fieldName = fields.MetadataFields[0].Name;
}
To know the type of a field, you only need to examine the .NET type of the field.
I typically use an "is" check, but you can also call GetType if you want.
For example:
var client = new SessionAwareCoreService2010Client();
client.ClientCredentials.Windows.ClientCredential.UserName = "myUserName";
client.ClientCredentials.Windows.ClientCredential.Password = "myPassword";
client.Open();
if (client.State == System.ServiceModel.CommunicationState.Opened)
{
var schemaUri = "tcm:1-47-8";
var fields= client.ReadSchemaFields(schemaUri, true, new ReadOptions());
foreach (var field in fields.MetadataFields)
{
if (field is SingleLineTextFieldDefinitionData)
{
// Do something specifically for single-line text fields
}
}
}
The ReadSchemaFields method exposes only the definition of the fields. So it is essentially a wrapper around the properties you enter while you define the field in a schema.
The Content and Metadata are exposed by ComponentData.Content and ComponentData.Metadata respectively. But those are exposed as XML strings, so you will have to do your own parsing of them.
If you (understandably) don't feel like that, have a look at this helper class: http://code.google.com/p/tridion-practice/wiki/ChangeContentOrMetadata
You might also want to read my answer to this question: Updating Components using the Core Service in SDL Tridion 2011

Accessing the object/row being edited in Dynamic Data

I'm modifying the "Edit.aspx" default page template used by ASP.NET Dynamic Data and adding some additional controls. I know that I can find the type of object being edited by looking at DetailsDataSource.GetTable().EntityType, but how can I see the actual object itself? Also, can I change the properties of the object and tell the data context to submit those changes?
Maybe you have found a solution already, however I'd like to share my expresience on this.
It turned out to be a great pita, but I've managed to obtain the editing row. I had to extract the DetailsDataSource WhereParameters and then create a query in runtime.
The code below works for tables with a single primary key. If you have compound keys, I guess, it will require modifications:
Parameter param = null;
foreach(object item in (DetailsDataSource.WhereParameters[0] as DynamicQueryStringParameter).GetWhereParameters(DetailsDataSource)) {
param = (Parameter)item;
break;
}
IQueryable query = DetailsDataSource.GetTable().GetQuery();
ParameterExpression lambdaArgument = Expression.Parameter(query.ElementType, "");
object paramValue = Convert.ChangeType(param.DefaultValue, param.Type);
Expression compareExpr = Expression.Equal(
Expression.Property(lambdaArgument, param.Name),
Expression.Constant(paramValue)
);
Expression lambda = Expression.Lambda(compareExpr, lambdaArgument);
Expression filteredQuery = Expression.Call(typeof(Queryable), "Where", new Type[] { query.ElementType }, query.Expression, lambda);
var WANTED = query.Provider.CreateQuery(filteredQuery).Cast<object>().FirstOrDefault<object>();
If it's a DD object you may be able to use FieldTemplateUserControl.FindFieldTemplate(controlId). Then if you need to you can cast it as an ITextControl to manipulate data.
Otherwise, try using this extension method to find the child control:
public static T FindControl<T>(this Control startingControl, string id) where T : Control
{
T found = startingControl.FindControl(id) as T;
if (found == null)
{
found = FindChildControl<T>(startingControl, id);
}
return found;
}
I found another solution, the other ones did not work.
In my case, I've copied Edit.aspx in /CustomPages/Devices/
Where Devices is the name of the table for which I want this custom behaviour.
Add this in Edit.aspx -> Page_Init()
DetailsDataSource.Selected += entityDataSource_Selected;
Add this in Edit.aspx :
protected void entityDataSource_Selected(object sender, EntityDataSourceSelectedEventArgs e)
{
Device device = e.Results.Cast<Device>().First();
// you have the object/row being edited !
}
Just change Device to your own table name.

Resources