Jira: How to obtain the previous value for a custom field in a custom IssueEventListener - event-handling

So how does one obtain the previous value of a custom field in a Jira IssueEventListener? I am writing a custom handler for the issueUpdated(IssueEvent) event and I would like to alter the handler's behavior if a certain custom field has changed. To detect the type of change I would like to compare the previous and current values.
(I'm am not asking about how to obtain its current value - I know how to get that from the related Issue)
I am developing against Jira 4.0.2 on Windows.
Is the best way to scan the change history for the last known value?
List changes = changeHistoryManager.getChangeHistoriesForUser(issue, user);

I'm assuming the original poster is writing a JIRA plugin with Java. I cannot be certain of how to accomplish this task in JIRA v4.0.2, but here is how I managed to do so with JIRA v5.0.2 (the solutions may very well be the same):
public void workflowEvent( IssueEvent event )
{
Long eventTypeId = event.getEventTypeId();
if( eventTypeId.equals( EventType.ISSUE_UPDATED_ID ) )
{
List<GenericValue> changeItemList = null;
try
{
changeItemList = event.getChangeLog().getRelated( "ChildChangeItem" );
}
catch( GenericEntityException e )
{
// Error or do what you need to do here.
e.printStackTrace();
}
if( changeItemList == null )
{
// Same deal here.
return;
}
Iterator<GenericValue> changeItemListIterator = changeItemList.iterator();
while( changeItemListIterator.hasNext() )
{
GenericValue changeItem = ( GenericValue )changeItemListIterator.next();
String fieldName = changeItem.get( "field" ).toString();
if( fieldName.equals( customFieldName ) ) // Name of custom field.
{
Object oldValue = changeItem.get( "oldvalue" );
Object newValue = changeItem.get( "newvalue" );
}
}
}
}
Some possible key values for changeItem are:
newvalue
oldstring
field
id
fieldtype
newstring
oldvalue
group
For many of the custom field types Object oldValue is probably just a String. But I don't think that's true for every case.

Try this example :
String codeProjetOldValue= "";
List<GenericValue> changeItemList = issueEvent.getChangeLog().getRelated("ChildChangeItem");
for (GenericValue genericValue : changeItemList) {
if(champCodeProjet.equals(genericValue.get("field"))){
codeProjetOldValue=genericValue.getString("oldstring");
break;
}
}
Note that : champCodeProjet is the name of customfield.

Related

Getting Document metadata (Document Type values) in liferay 7

I am working on Liferay 7. I created a document type "My Documents" with field "Language" which is a selection dropdown with values "English", "French" and "Spanish". I uploaded a document and selected Language value as French. Now I am trying to get this Language value for the document but its returning blank. Below is the code I am using.
DDMStructure ddmStructure = null;
List<DDMStructure> structures = dLFileEntryType.getDDMStructures();
mainloop:
for (DDMStructure struct : structures) {
if (struct.getName((Locale.ROOT)).equalsIgnoreCase("My Document")) {
ddmStructure = struct;
break mainloop;
}
}
DLFileEntryMetadata fileEntryMetadata = null;
try {
fileEntryMetadata = DLFileEntryMetadataLocalServiceUtil.getFileEntryMetadata(ddmStructure.getStructureId(), dlFileEntry.getFileVersion().getFileVersionId());
if(Validator.isNotNull(fileEntryMetadata)) {
ServiceContext serviceContextDLFile = new ServiceContext();
serviceContextDLFile.setCompanyId(companyId);
serviceContextDLFile.setAttribute("fileEntryTypeId", fileEntryTypeId);
serviceContextDLFile.setAttribute("fileEntryMetadataId", fileEntryMetadata.getFileEntryMetadataId());
serviceContextDLFile.setAttribute("DDMStorageId", fileEntryMetadata.getDDMStorageId());
serviceContextDLFile.setAttribute("fileEntryId", fileEntryMetadata.getFileEntryId());
serviceContextDLFile.setAttribute("fileVersionId", fileEntryMetadata.getFileVersionId());
DDMFormValues ddmFormValues = StorageEngineManagerUtil.getDDMFormValues(fileEntryMetadata.getDDMStructureId(), null, serviceContextDLFile);
List<DDMFormFieldValue> ddmFormFieldValues = ddmFormValues.getDDMFormFieldValues();
if(Validator.isNotNull(ddmFormFieldValues) && !ddmFormFieldValues.isEmpty()) {
for(DDMFormFieldValue formfieldValue : ddmFormFieldValues) {
if(formfieldValue.getName().equalsIgnoreCase("Language")) {
String languageRawName = formfieldValue.getValue().getString(Locale.US);
String language = languageRawName.replace("[\"", "").replace("\"]", "");
}
}
}
}
} catch (NoSuchFileEntryMetadataException nsfene) {
// LOGGER.error("ERROR:: ", nsfene);
} catch(PortalException portalException) {
// LOGGER.error("ERROR:: " , portalException);
}
I have not given any predefined value for Language field while creating Document Type. When I am giving any predefined value for Language field, the above code is returning that predefined value.
Please tell if I am missing something or there is any other approach do achieve this.
Stored data in document library documents is not internationalized.
I think you have to always use the default language of the instance.

Custom properties are not updated for the word via openXML

I am trying to update custom properties of word document thru Open XML programming but it seems the updated properties are not getting saved properly for the word document. So when I opening document after successful execution of the update custom property code, I am getting the message box which is "This document contains field that may refer to other files; Do you want to update the fields in the Document?" If I am pressing 'NO' button then all the update properties would not be saved to the document. If we are going for yes option then it will update properties but I need to save the properties explicitly. Please suggest to save properties to the document without getting confirmation message or corrupting the document. :)
the code snippet is given as below,
public void SetCustomValue(
WordprocessingDocument document, string propname, string aValue)
{
CustomFilePropertiesPart oDocCustomProps = document.CustomFilePropertiesPart;
Properties props = oDocCustomProps.Properties;
if (props != null)
{
//logger.Debug("props is not null");
foreach (var prop in props.Elements<CustomDocumentProperty>())
{
if (prop != null && prop.Name == propname)
{
//logger.Debug("Setting Property: " + prop.Name + " to value: " + aValue);
prop.Remove();
var newProp = new CustomDocumentProperty();
newProp.FormatId = "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}";
newProp.Name = prop.Name;
VTLPWSTR vTLPWSTR1 = new VTLPWSTR();
vTLPWSTR1.Text = aValue;
newProp.Append(vTLPWSTR1);
props.AppendChild(newProp);
props.Save();
}
}
int pid = 2;
foreach (CustomDocumentProperty item in props)
{
item.PropertyId = pid++;
}
props.Save();
}
}
I am using .Net framework 3.5 with Open XML SDK 2.0 and Office 2013.
Try this one
var CustomeProperties = xmlDOc.CustomFilePropertiesPart.Properties;
foreach (CustomDocumentProperty customeProperty in CustomeProperties)
{
if (customeProperty.Name == "DocumentName")
{
customeProperty.VTLPWSTR = new VTLPWSTR("My Custom Name");
}
else if (customeProperty.Name == "DocumentID")
{
customeProperty.VTLPWSTR = new VTLPWSTR("FNP.SMS.IQC");
}
else if (customeProperty.Name == "DocumentLastUpdate")
{
customeProperty.VTLPWSTR = new VTLPWSTR(DateTime.Now.ToShortDateString());
}
}
//Open Word Setting File
DocumentSettingsPart settingsPart = xmlDOc.MainDocumentPart.GetPartsOfType<DocumentSettingsPart>().First();
//Update Fields
UpdateFieldsOnOpen updateFields = new UpdateFieldsOnOpen();
updateFields.Val = new OnOffValue(true);
settingsPart.Settings.PrependChild<UpdateFieldsOnOpen>(updateFields);
settingsPart.Settings.Save();
you have to update your document fields on open.

declare variable to store linq entity for conditional statements

I am trying to look up record using if I have the key then use Find if not use Where
private ApplicationDbContext db = new ApplicationDbContext();
public bool DeactivatePrice(int priceId = 0, string sponsorUserName = "")
{
var prices = db.BeveragePrices;
// if we have an id then find
if (priceId != 0)
{
prices = prices.Find(priceId);
}
else
{
prices = prices.Where(b => b.UserCreated == sponsorUserName);
}
if (prices != null)
{
// do something
}
return true;
I get the following error for
prices = prices.Find(priceId);
Cannot convert app.Model.BeveragePrices from system.data.entity.dbset
I am copying the pattern from this answer but something must be different.
Seems you forgot to put a predicate inside the Find function call. Also you need to do ToList on the collection. The second option is a lot more efficient. The first one gets the whole collection before selection.
Another note commented by #Alla is that the find returns a single element. So I assume another declaration had been made for 'price' in the first option I state down here.
price = prices.ToList.Find(b => b.PriceId == priceId);
Or
prices = prices.Select(b => b.PriceId == priceId);
I assume the field name is PriceId.

CRM 2011 : Plugin to create duplicate records

i created a simple plugin to create a duplicate record that refers to the parent record.
Here is my code
var pluginExecutionContext = localContext.PluginExecutionContext;
IOrganizationService service = localContext.OrganizationService;
abc= pluginExecutionContext.InputParameters["Target"] as Entity;
if (pluginExecutionContext.Depth == 1)
{
Guid abcId = abc.Id;
Entity abcCopy = new Entity("mcg_abc");
if (abc.Attributes.Contains("mcg_abccategoryoptioncode"))
{
abcCopy.Attributes["mcg_abccategoryoptioncode"] = abc.GetAttributeValue<OptionSetValue>("mcg_abccategoryoptioncode");
}
if (abc.Attributes.Contains("mcg_effectivedate"))
{
abcCopy.Attributes["mcg_effectivedate"] = isp.GetAttributeValue<DateTime>("mcg_effectivedate");
}
if (abc.Attributes.Contains("mcg_startdate"))
{
abcCopy.Attributes["mcg_startdate"] = isp.GetAttributeValue<DateTime>("mcg_startdate");
}
if (abc.Attributes.Contains("mcg_enddate"))
{
abcCopy.Attributes["mcg_enddate"] = isp.GetAttributeValue<DateTime>("mcg_enddate");
}
if (abc.Attributes.Contains("mcg_amendeddate"))
{
abcCopy.Attributes["mcg_amendeddate"] = isp.GetAttributeValue<DateTime>("mcg_amendeddate");
}
if ((abc.GetAttributeValue<OptionSetValue>("mcg_abccategoryoptioncode").Value) == 803870001)
{
//Some more fields;
}
else
{
//Some more fields;
}
// SOme more fields;
abcCopy.Attributes["mcg_parentabc"] = new EntityReference("mcg_abc", abc.Id);
service.Create(abcCopy);
}
Now the problem is all the fields before the below check are getting copied
if ((abc.GetAttributeValue<OptionSetValue>("mcg_abccategoryoptioncode").Value) == 803870001)
However fields after this check are not getting copied.
Please if anybody could suggest what mistake i have made.
In case you take field from Target - this field was updated on a client side. In case field was not updated - it would not be in Target. You should use Images to get values of unchanged fields.
The field must be empty so a exception may arise. Try to use the plugin image or change your code to this way:
if (abc.Attributes.Contains("mcg_abccategoryoptioncode")){
if ((abc.GetAttributeValue<OptionSetValue>("mcg_abccategoryoptioncode").Value) == 803870001)
....

In KRL, how do I detect if a variable is an array or hash?

In KRL, I'd like to detect whether a variable is an array or hash so that I know if I need to use the decode or encode operator on it. Is that possible?
I'd like to do something like this:
my_var = var.is_array => var.decode() | my_var
Update
The best way to do this is with the typeof() operator. This is new since the answer, but with the early interpretation of variables, the old way listed in the answer will no longer work.
Another useful operator for examining your data is isnull()
myHash.typeof() => "hash"
myArray.typeof() => "array"
...
The only way that I have figured out how to detect the data structure type is by coercing to a string and then checking to see if the resulting pointer string contains the word 'array' or 'hash'.
'One liner'
myHashIsHash = "#{myHash}".match(re/hash/gi);
myHashIsHash will be true/1
Example app built to demonstrate concept
ruleset a60x547 {
meta {
name "detect-array-or-hash"
description <<
detect-array-or-hash
>>
author "Mike Grace"
logging on
}
global {
myHash = {
"asking":"Mike Farmer",
"question":"detect type"
};
myArray = [0,1,2,3];
}
rule detect_types {
select when pageview ".*"
pre {
myHashIsArray = "#{myHash}".match(re/array/gi);
myHashIsHash = "#{myHash}".match(re/hash/gi);
myArrayIsArray = "#{myArray}".match(re/array/gi);
myArrayIsHash = "#{myArray}".match(re/hash/gi);
hashAsString = "#{myHash}";
arrayAsString = "#{myArray}";
}
{
notify("hash as string",hashAsString) with sticky = true;
notify("array as string",arrayAsString) with sticky = true;
notify("hash is array",myHashIsArray) with sticky = true;
notify("hash is hash",myHashIsHash) with sticky = true;
notify("array is array",myArrayIsArray) with sticky = true;
notify("array is hash",myArrayIsHash) with sticky = true;
}
}
}
Example app in action!