Is it possible to validate a value before it is set with Eclipse EMF validation framework? - eclipse-emf

The way I understand how eclipse validation framework works:
generate an object with a factory
set a value for an attribute in this object
check validation
For example:
public class ValidateNameTest {
public static void main(String[] args) {
ExtlibraryPackageImpl.init();
ExtlibraryFactory factory = ExtlibraryFactory.eINSTANCE;
Writer writer = factory.createWriter();
// comment next line for false result in console
writer.setName("test");
writer.setFirstName("test");
writer.setLastName("test");
boolean isNull = (writer.getName() == null) ? true : false;
System.out.println("writer name is null : " + isNull);
boolean result = validateObject(writer);
System.err.println("result = " + result);
boolean result2 = validateObject2(writer);
System.err.println("result2 = " + result2);
boolean result3 = validateObject3(writer);
System.err.println("result3 = " + result3);
boolean result4 = validateObject5(writer);
System.out.println("result4 = " + result4);
}
public static boolean validateObject(Writer writer) {
ExtlibraryValidator validator = ExtlibraryValidator.INSTANCE;
if (!validator.validateWriter_hasValidName(writer, null, null)) {
return false;
}
return true;
}
public static boolean validateObject2(EObject eObject) {
EValidator validator = EValidator.Registry.INSTANCE
.getEValidator(eObject.eClass().getEPackage());
if (validator != null) {
if (!validator.validate(eObject, null, null)) {
return false;
}
}
return true;
}
public static boolean validateObject3(EObject eObject) {
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eObject);
return diagnostic.getSeverity() == Diagnostic.OK;
}
public static boolean validateObject5(EObject eObject)
{
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(eObject);
if (diagnostic.getSeverity() == Diagnostic.ERROR || diagnostic.getSeverity() == Diagnostic.WARNING)
{
System.err.println(diagnostic.getMessage());
for (Diagnostic childDiagnostic : diagnostic.getChildren())
{
switch (childDiagnostic.getSeverity())
{
case Diagnostic.ERROR:
case Diagnostic.WARNING:
System.err.println("\t" + childDiagnostic.getMessage());
}
}
return false;
}
return true;
}
}
But I want to check if a value is valid for the model before I call the setter for the attribute. Is this possible with Eclipse EMF validation framework? Can somebody give an example please?

I know of one common use case where this is possible: Data binding between model and UI controls.
When you establish the EMF data binding between your model and the user interface, you can validate user input as follows. Create an update strategy (target to model) and override the method validateBeforeSet(Object). Here is an example:
EMFDataBindingContext ctx = new EMFDataBindingContext();
ISWTObservableValue notesObservableValue = prop.observe(swtTextViewer);
IEMFValueProperty notesValueProperty = EMFProperties.value(ModelPackage.Literals.THING__NOTES);
UpdateValueStrategy targetToModel = new UpdateValueStrategy() {
#Override
public IStatus validateBeforeSet(Object value) {
if ("".equals(value)) {
MessageDialog.openError(Display.getCurrent()
.getActiveShell(), "Error",
"You should supply a description");
return ValidationStatus
.error("You should supply a description");
}
return super.validateBeforeSet(value);
}
};
ctx.bindValue(notesObservableValue,
notesValueProperty.observe(thing), targetToModel,
new UpdateValueStrategy());

Related

PCF Not firing updateview without Resize Browser

Created a PCF control, working fine in harnes tool. After integrating to D365 , updateview()not being called. Once I click the developertool then it is working. If am not opening developer tool OR REsize the browser window, then updateview is not being called even though data changed.
Onresetclick am calling notifychanged event , though it is not triggering the updateview
private onResetClick = (newValue: boolean, props: ToggleProps): void => {
if (newValue) {
//isReset true -> clicked set button, action to grey out toggle and change button name to set
if (!this.changeProps.isControlDisabledInForm) {
this._isChanged = true;
this.isReset = this.changeProps.isReset = newValue;
this.changeProps.buttonProperties.checkbox.disabled = true;
this.changeProps.buttonProperties.checkbox.checked = false;
this._selectedOptionID = null;
// this.theNotifyChanged();
}
} else {
if (!this.changeProps.isControlDisabledInForm) {
this._isChanged = true;
this.changeProps.buttonProperties.checkbox.disabled = false;
this.isReset = this.changeProps.isReset = newValue;
this._selectedOptionID
= this.changeProps.optionsetValues.nokey;
// this.theNotifyChanged();
}
}
if (this.theNotifyChanged) {
this.theNotifyChanged();
}
};
/**
* Called when any value in the property bag has changed. This includes field values, data-sets, global values such as container height and width, offline status, control metadata values such as label, visible, etc.
* #param context The entire property bag availabel to control via Context Object; It contains values as set up by the customizer mapped to names defined in the manifest, as well as utility functions
*/
public updateView(context: ComponentFramework.Context<IInputs>): void {
this._context = context;
this.changeProps.isControlDisabledInForm = context.mode.isControlDisabled;
this.changeProps.isVisible = context.mode.isVisible;
this._checkboxID = context.parameters.OptionSetAttribute.attributes?.LogicalName ?? uuidv4();
let selBoolean: boolean = false;
if (!this._isChanged) {
this._selectedOptionID = context.parameters.OptionSetAttribute.raw;
// this.SetButtonProperties(selBoolean);
}
else {
//if (this.changeProps.isReset) {
// // this.changeProps.buttonProperties.checkbox.disabled = true;
// // this.changeProps.buttonProperties.checkbox.checked = false;
//}
//else {
// // this.changeProps.buttonProperties.checkbox.disabled = false;
//}
selBoolean = this.isReset as boolean;//this.changeProps.buttonProperties.checkbox.checked;
}
if (this.optionSetArray) {
for (var i = 0; i < this.optionSetArray.length; i++) {
if (this.optionSetArray[i].Value == this._selectedOptionID) {
this.SelectedOptionSetLabel = this.optionSetArray[i].Label;
}
if (this.optionSetArray[i]?.Label.toUpperCase() === "YES") { //TODO : this needs to be generic not fixed with yes
this.changeProps.optionsetValues.yeskey = this.optionSetArray[i].Value;
} else {
this.changeProps.optionsetValues.nokey = this.optionSetArray[i].Value;
}
}
}
if (!this._isChanged) {
if (this.SelectedOptionSetLabel != null && this.SelectedOptionSetLabel != undefined) {
this.changeProps.buttonProperties.checkbox.checked = this.SelectedOptionSetLabel?.toUpperCase() === "YES" ? true as boolean : false as boolean;//TODO : this needs to be generic not fixed with yes
selBoolean = this.changeProps.isReset = this.isReset = true;
} else {
selBoolean = false;
this.changeProps.isReset = this.isReset = false;
}
}
this._messageContent = selBoolean ? this.changeProps.labels.trueLabel : this.changeProps.labels.falseLabel;
this.changeProps.buttonProperties = {
resetButton: { innerHTML: selBoolean ? "Reset" : "Set" },// when there is a value stored in attribute we need to show Reset
messageContent: this._messageContent,
checkbox: {
disabled: this.changeProps.isControlDisabledInForm ? true : (this.isReset ? false : true),
checked: this.changeProps.buttonProperties.checkbox.checked, checkboxID: this._checkboxID
}
};
console.log("inside ts");
ReactDOM.render(
React.createElement(ToggleButton, this.changeProps
), this.container);
}
Though the context got changed , scope goes to getOutput() method to check if there is any change in output then only PCF view get rerender. In my case, i didnot change the output value in getoutput() method so it was not working.
Here "_selectedOptionID" value should be changed then it started working.
public getOutputs(): IOutputs {
return {
OptionSetAttribute: this._selectedOptionID as number
};
}

File upload field validation in Web Forms for Marketers 8.1 update 3

I am trying file upload validation in sitecore 8 using Web forms for Marketers but it is not working please suggest me solution. Here is my code.
namespace Test.Web.WFFM
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class LimitFileSizeAttribute : DynamicValidationBase
{
private const string FileSizeLimitKey = "filesizelimit";
private const string ErrorMessageKey = "filesizelimiterror";
protected override ValidationResult ValidateFieldValue(IViewModel model, object value, ValidationContext validationContext)
{
// Required attribute should handle null value
if (value == null)
{
return ValidationResult.Success;
}
var fileBase = value as HttpPostedFileBase;
if (fileBase == null)
{
return new ValidationResult(ErrorMessage);
}
var fileUploadField = validationContext.ObjectInstance as FileUploadField;
var limit = GetLimit(fileUploadField);
if (limit == -1) // Limit not set
{
return ValidationResult.Success;
}
if (fileBase.ContentLength > limit)
{
return new ValidationResult(GetErrorMessage(fileUploadField));
}
return ValidationResult.Success;
}
private static int GetLimit(IViewModel field)
{
if (field == null || !field.Parameters.ContainsKey(FileSizeLimitKey))
{
return -1;
}
var parameter = field.Parameters[FileSizeLimitKey];
int intValue;
if (int.TryParse(parameter, out intValue))
{
return intValue;
}
return -1;
}
private string GetErrorMessage(IViewModel field)
{
if (field != null && field.Parameters.ContainsKey(ErrorMessageKey))
{
return field.Parameters[ErrorMessageKey];
}
return ErrorMessage;
}
}}
Created RestrictedUploadField class
namespace Test.Web.WFFM.MVC
{
public class RestrictedUploadField : FileUploadField
{
[LimitFileSize]
public override HttpPostedFileBase Value { get; set; }
}}
Created custom validation in sitecore and added "Parameters" and "Localized Parameters"
Created custom field type "Restricted File Upload", added validation in "Validation" field, added "Parameters" and "Localized Parameters".

Assign ajax result to interface inclusive methods

I'm quite new to Typescript and have a bit of a problem to get my code working. I have the following interface/class structure
interface IInterface {
id : number;
method() : string;
}
class IClass implements IInterface {
id : number;
method() : string { return "foo";}
}
Now I want to get some data from a webservice via the following call
$.get("/some/url", (data : Array<IInterface>) => {
for (var i = 0; i < data.length; i++) {
console.log(data[i].id);
console.log(data[i].method());
}
});
While this compiles perfectly fine in typescript and also all properties are set perfectly fine, I get a runtime TypeError data[i].method is not a function
So now my question: How can I cast/assign (?) this correctly, so that the methods are also available in the resulting JavaScript?
UPDATE As requested: a dump of the data I get from the webservice.
data = [{id : 1}, {id : 2}, ...]
Of course, this is a simplified example, the real classes/interfaces have some more properties (they all are assigned correctly), but also only one method (so far, when I get it working, some more will follow).
The problem is what you receive are objects which are complying to the interface, but they don't have a method property inside.
What you need to do in order to get this working is, you need to create new objects from type IClass in the reponse handler which extend the objects inside data:
$.get("/some/url", (data: Array<IInterface>) => {
return data.map((d) => return new IClass(d.id));
});
This is a common problem of converting JSON objects into instances of the classes. There are some proposals discussed here: JSON to TypeScript class instance?
Below is the solution I came up to do such deserialization:
export class Helper
{
public static DESCRIPTOR_SIGN = '$';
private static m_entityModules = [];
private static ReviveDateTime(key: any, value: any): any
{
if (typeof value === 'string')
{
let a = /\/Date\((\d*)\)\//.exec(value);
if (a)
{
return new Date(+a[1]);
}
}
return value;
}
private static RessurectValue(json: any, environments: any[]): any
{
if(json == null)
{
return null;
}
else if(Helper.IsString(json))
{
return json;
}
else if(json instanceof Date)
{
return json;
}
else if(typeof json === 'object')
{
return Helper.RessurectInternal(json, environments);
}
else
{
return json;
}
}
private static RessurectInternal(json: any, environments: any[]): any
{
var instance;
if(!json[Helper.DESCRIPTOR_SIGN])
{
instance = {};
}
else
{
instance = Helper.CreateObject(json[Helper.DESCRIPTOR_SIGN]);
if(Helper.IsUndefined(instance))
{
throw new Error('Unknown type to deserialize:' + json[Helper.DESCRIPTOR_SIGN]);
}
}
for(var prop in json)
{
if(!json.hasOwnProperty(prop) || prop === Helper.DESCRIPTOR_SIGN)
{
continue;
}
let val = json[prop];
instance[prop] = Helper.Ressurect(val, environments);
}
return instance;
}
private static CreateObject(className: string, environments?: any[]): any
{
let instance: any;
for(let e of environments)
{
var construct = e[className];
if(!Helper.IsUndefined(construct))
{
instance = new construct();
break;
}
}
return instance;
}
private static IsNumber(val: any): boolean
{
return typeof val == 'number' || val instanceof Number;
}
private static IsUndefined(val: any): boolean
{
return typeof(val) === 'undefined';
}
private static IsString(val: any): boolean
{
return typeof val == 'string' || val instanceof String;
}
/**
* Deserialize json object object into TypeScript one.
* #param json json object that must have its class name in '$' field
* #param environments list of modules containing all types that can be encountered during deserialization
* #return deserialized typescript object of specified type
*/
public static Ressurect(val: any, environments: any[]): any
{
if(val instanceof Array)
{
if(val.length == 0)
{
return val;
}
else
{
let firstElement = val[0];
if(typeof firstElement !== 'object')
{
return val;
}
else
{
let arr = [];
for (var i = 0; i < val.length; i++)
{
var element = val[i];
arr.push(Helper.RessurectValue(element, environments));
}
return arr;
}
}
}
else
{
return Helper.RessurectValue(val, environments);
}
}
}
Some notes for the above. It works based on the assumption that:
There is a parameterless constructor in every type that can be deserialized.
Every JSON object contain field '$' with its class name inside.
Sample of usage. Lets suppose yu have defined all your serializable classes in one external mode called 'Types'. Then to deserialize JSON object you write:
import * as types from './Types'
//Some code to get jsonObj that has jsonObj.$ set to "RealObject" - a type from "Types" module
let realObj = <types.RealObject>Helper.Resurrect(jsonObj, [types]);
Hope this helps.

How can I upload image and post some datas to MVC4 wep api method?

I have tried for days but I couldn't reach any successful result. I need to post images with their information (s.t. created user name).
This is my method;
[HttpPost]
public Task<HttpResponseMessage> PostFile(string createdByName)
{
HttpRequestMessage request = this.Request;
if (!request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = System.Configuration.ConfigurationSettings.AppSettings["TempUploadDir"];
var provider = new MultipartFormDataStreamProvider(root);
var task = request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(o =>
{
AddImages(provider.BodyPartFileNames);
string file1 = provider.BodyPartFileNames.First().Value;
// this is the file name on the server where the file was saved
return new HttpResponseMessage()
{
Content = new StringContent("File uploaded.")
};
}
);
return task;
}
And this my TypeFormatterClass which is added global.asax
public class MultiFormDataMediaTypeFormatter : FormUrlEncodedMediaTypeFormatter
{
public MultiFormDataMediaTypeFormatter()
: base()
{
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));
}
protected override bool CanReadType(Type type)
{
return true;
}
protected override bool CanWriteType(Type type)
{
return false;
}
protected override Task<object> OnReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext)
{
var contents = formatterContext.Request.Content.ReadAsMultipartAsync().Result;
return Task.Factory.StartNew<object>(() =>
{
return new MultiFormKeyValueModel(contents);
});
}
class MultiFormKeyValueModel : IKeyValueModel
{
IEnumerable<HttpContent> _contents;
public MultiFormKeyValueModel(IEnumerable<HttpContent> contents)
{
_contents = contents;
}
public IEnumerable<string> Keys
{
get
{
return _contents.Cast<string>();
}
}
public bool TryGetValue(string key, out object value)
{
value = _contents.FirstDispositionNameOrDefault(key).ReadAsStringAsync().Result;
return true;
}
}
}
When I post images and "createdByName" I can reach images but I couldn't parameters. How can I do this?
Thank you.
To get your createdByName field, inside your ContinueWith :
var parts = o.Result;
HttpContent namePart = parts.FirstDispositionNameOrDefault("createdByName");
if (namePart == null)
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
string name = namePart.ReadAsStringAsync().Result;
For a more detailed example, see :
http://www.asp.net/web-api/overview/working-with-http/html-forms-and-multipart-mime#multipartmime

The correct display name/field for a list item in a Sharepoint list (using Web Services)

I'm creating a program that uses SharePoint Web Services to query and show a Sharepoint list to the user. I can only show one column at a time, so I need to find a 'default column' or 'display column' to show. I know 'Title' is commonly used in many of the content types but I want this to be robust with any type of custom content type or list so I would like to find some way of querying the list to discover this field.
For example: I'm using SharePoint Manager 2010 here and looking at a Link Library (That doesn't have a Title field) but somehow it knows that the list item is called 'http://google.com'. How is it inferring this?
(source: adamburkepile.com)
Looks like DisplayName has quite a bit of logic behind it. Here is the code I got using Reflector:
public string DisplayName
{
get
{
if (!this.IsNew)
{
if ((!this.ParentList.AllowContentTypes && (this.ParentList.BaseType == SPBaseType.DocumentLibrary)) || (this.ParentList.AllowContentTypes && (this.ContentTypeId.IsNonDiscussionFolder || this.ContentTypeId.IsChildOf(SPBuiltInContentTypeId.Document))))
{
string str = (string) this.GetValue("BaseName", false);
if (!string.IsNullOrEmpty(str))
{
return SPHttpUtility.HtmlDecode(str);
}
}
SPField fieldByInternalName = this.Fields.GetFieldByInternalName("Title", false);
if (fieldByInternalName != null)
{
string fieldValueAsText = fieldByInternalName.GetFieldValueAsText(this.GetValue(fieldByInternalName, -1, false));
if (!string.IsNullOrEmpty(fieldValueAsText))
{
return fieldValueAsText;
}
}
if (this.ParentList.AllowContentTypes)
{
if (this.ContentTypeId.IsChildOf(SPBuiltInContentTypeId.Link))
{
SPFieldUrlValue value2 = new SPFieldUrlValue((string) this.GetValue("URL", false));
if (!string.IsNullOrEmpty(value2.Description))
{
return value2.Description;
}
if (!string.IsNullOrEmpty(value2.Url))
{
return value2.Url;
}
}
if (this.ContentTypeId.IsChildOf(SPBuiltInContentTypeId.Message))
{
Guid discussionTitleLookup = SPBuiltInFieldId.DiscussionTitleLookup;
SPField fld = this.Fields[discussionTitleLookup];
string str3 = fld.GetFieldValueAsText(this.GetValue(fld, -1, false));
if (!string.IsNullOrEmpty(str3))
{
return str3;
}
}
}
if (this.ParentList.BaseType != SPBaseType.Survey)
{
using (IEnumerator enumerator = this.Fields.GetEnumerator())
{
SPField field3;
string str5;
while (enumerator.MoveNext())
{
field3 = (SPField) enumerator.Current;
if (field3.GetFieldBoolValue("TitleField"))
{
goto Label_00C6;
}
}
goto Label_016F;
Label_00BB:
if (!(field3 is SPFieldMultiLineText))
{
return str5;
}
goto Label_00ED;
Label_00C6:
str5 = field3.GetFieldValueAsText(this.GetValue(field3, -1, false));
if (string.IsNullOrEmpty(str5))
{
goto Label_016F;
}
goto Label_00BB;
Label_00ED:
if (str5.Length <= 0xff)
{
return str5;
}
return str5.Substring(0, 0xff);
}
}
SPContext context2 = SPContext.Current;
if ((context2 == null) || (context2.FormContext.FormMode != SPControlMode.Edit))
{
return SPResource.GetString("ViewResponseTitle", new object[] { this.ID.ToString("N0", this.Web.Locale) });
}
return SPResource.GetString("ToolBarMenuRespondToSurvey", new object[0]);
}
SPContext current = SPContext.Current;
if (this.ParentList.BaseType != SPBaseType.Survey)
{
if ((current != null) && current.FormContext.IsNonDiscussionFolder)
{
return SPResource.GetString("ButtonTextNewFolder", new object[0]);
}
return SPResource.GetString("NewFormTitleNewItem", new object[0]);
}
return SPResource.GetString("ToolBarMenuRespondToSurvey", new object[0]);
Label_016F:
return SPResource.GetString("NoTitle", new object[0]);
}
}