Groovy: Why are equal GPathResult instances generating different hashCodes? - groovy

I was playing around with adding some XmlSlurper elements to a Set and making sure a slurper that parsed the same text as another wouldn't be added twice.
def CAR_RECORDS = '''
<records>
<car name='HSV Maloo' make='Holden' year='2006'>
<country>Australia</country>
<record type='speed'>
Production Pickup Truck with speed of 271kph
</record>
</car>
<car name='P50' make='Peel' year='1962'>
<country>Isle of Man</country>
<record type='size'>
Smallest Street-Legal Car at 99cm wide and 59 kg in weight
</record>
</car>
<car name='Royale' make='Bugatti' year='1931'>
<country>France</country>
<record type='price'>Most Valuable Car at $15 million</record>
</car>
</records>
'''
def records = new XmlSlurper().parseText(CAR_RECORDS)
def same_records = new XmlSlurper().parseText(CAR_RECORDS)
// obviously equal
assert records == same_records
def slurpers = new HashSet()
slurpers.add(records)
slurpers.add(same_records)
//why are there 2 entries here?
assert slurpers.size() == 1
Am I missing something? Shouldn't two objects that are equal generate the same hashCode?
Same thing happens for a map with an XmlSlurper as a key.

Looks like GPathResult overrides equals method but use default hashCode from Object. Thats why records and same_records are equals with different hashcodes.
http://groovy.codehaus.org/api/groovy/util/slurpersupport/GPathResult.html

Related

How to add two float fields with different currency sign?

We have already Amount field on invoice lines which shows the amount in the currency selected on invoice. I want to convert the same amount to base currency and also show the base currency amount on invoice lines with base currency symbol.
For this purpose I have added new many2one field for base currency as show below:
base_currency_id = fields.Many2one('res.currency', default=lambda self: self.invoice_id.company_id.currency_id.id)
Then I added new float field for computing the amount in base currency like this:
#api.onchange('price_subtotal', 'invoice_id.currency_id')
def compute_amount_in_base_currency(self):
company_currency = self.invoice_id.company_id.currency_id
for l in self:
amount_in_base = l.currency_id.compute(l.price_subtotal, company_currency)
l.amount_in_base = amount_in_base
amount_in_base = fields.Float('Base Amount', readonly=True, compute='compute_amount_in_base_currency')
In xml file I have added base_currency_id field and made it invisible. Then added amount_in_base field to the view with widget='monetary' and options="{'currency_field': 'base_currency_id'}". My xml file looks like this:
<xpath expr="//field[#name='invoice_line_ids']/tree/field[#name='price_subtotal']" position="after">
<field name="base_currency_id" invisible="True"/>
<field name="amount_in_base" widget="monetary" options="{'currency_field': 'base_currency_id'}"/>
</xpath>

Hide the related Many2One field when creating a record from a one2Many Relationship

i have a One2many relationship.
class Osg(models.Model):
_name = "men_projet.osg"
_rec_name = 'nom'
sequence = fields.Char('Sequence', readonly=True)
nom = fields.Char('Nom')
responsable = fields.Many2one('res.partner')
programme_id = fields.Many2one('men_projet.programme')
os = fields.One2many('men_projet.os', 'osg_id') <---- My One2many field.
class Os(models.Model):
_name = "men_projet.os"
_rec_name = "nom"
sequence = fields.Char('Sequence', readonly=True)
nom = fields.Char('Nom')
responsable = fields.Many2one('res.partner')
osg_id = fields.Many2one('men_projet.osg') <---- The inverse field
My Goal : When adding a new record to the One2Many table (Using the 'add a line button') the modal/pop-up window has the inverse Many2one field (Dropdown) which makes no sense since i'm already coming from the Model and having it's value.
So i want to hide it when creating the Model 'Os' from the One2Many field while letting it visible when creating it from it's own action.
Make a FormView for that One2many field.
Example:-
<field name="os" >
<form>
<group>
<field name="sequence"/>
<field name="nom"/>
<field name="responsable"/>
</group>
</form>
</field>

Create SharePoint CAML recurring calendar item

I'm using the Lists.asmx webservices to connect to my SharePoint 2010 server. I can upload a new calendar item using the below XML, but I can't figure out what field to add so that it's a "recurring every weekday" instead of an event that spans multiple days.
<Batch OnError="Continue" ListVersion="1" ViewName="">
<Method ID="1" Cmd="New">
<Field Name="Title">Test Event</Field>
<Field Name="EventDate">2018-10-01 00:00:00</Field>
<Field Name="EndDate">2018-10-01 23:59:59</Field>
<Field Name="fAllDayEvent">1</Field>
<Field Name="fRecurrence">1</Field>
<Field Name="EventType">1</Field>
<Field Name="UID">{17ea5230-d1f4-4fe2-acc2-450e839998ee}</Field>
<Field Name="RecurrenceData"><![CDATA[<recurrence>
<rule>
<firstDayOfWeek>su</firstDayOfWeek>
<repeat>
<weekly mo="TRUE" tu="TRUE" we="TRUE" th="TRUE" fr="TRUE" weekFrequency="1" />
</repeat>
<repeatInstances>10</repeatInstances>
</rule>
</recurrence>]]></Field>
</Method>
</Batch>
I'm creating the code as shown in this gist
You'll need to include two additional parameters are part of your event creation - one to let SharePoint know it is a recurring event (fRecurrence, a Boolean value) and another with the actual recurrence pattern (RecurrenceData, an XML string).
You can read more about the structure of the RecurrenceData XML here:
http://thehightechheels.blogspot.com/2012/12/sharepoint-evenet-recurrencedata-xml.html
There's quite a bit to it so rather than re-stating everything there, I'll share an example of how to create an event that recurs each weekday as requested:
<recurrence>
<rule>
<firstDayOfWeek>su</firstDayOfWeek>
<repeat>
<weekly mo="TRUE" tu="TRUE" we="TRUE" th="TRUE" fr="TRUE" weekFrequency="1" />
</repeat>
<repeatForever>FALSE</repeatForever>
</rule>
</recurrence>
Generally speaking a recurrence rule has 3 parts: the day of the week considered the first day; the pattern for repeating the event, and; when it ends, which can be never, after 'n' occurrences or by a certain calendar date.
Within the <repeat> section is where you have a lot of flexibility to set the pattern. For your scenario, the use of the <weekly> element combined with the weekFrequency parameter ensures this event will repeat every week. Within that week, we can then set which days of the week are to include the event; by setting Monday through Friday to "TRUE" (mo, tu, we, th, fr) we're telling SharePoint to repeat the event each of those days.
Summarizing the full Batch XML changes discussed in the comments below, here is the input I've used on my local SP2010 environment:
<Batch OnError="Return">
<Method ID="1" Cmd="New">
<Field Name="Title">Test Event</Field>
<Field Name="EventDate">2018-10-01 00:00:00</Field>
<Field Name="EndDate">2018-10-01 23:59:59</Field>
<Field Name="fAllDayEvent">1</Field>
<Field Name="fRecurrence">1</Field>
<Field Name="EventType">1</Field>
<Field Name="Duration">86340</Field>
<Field Name="WorkspaceLink">0</Field>
<Field Name="TimeZone">0</Field>
<Field Name="UID">{17ea5230-d1f4-4fe2-acc2-450e839998ee}</Field>
<Field Name="RecurrenceData"><![CDATA[
<recurrence>
<rule>
<firstDayOfWeek>su</firstDayOfWeek>
<repeat>
<daily weekday="TRUE" />
</repeat>
<repeatInstances>7</repeatInstances>
</rule>
</recurrence>]]>
</Field>
</Method>
</Batch>
Which yields this:
Just to make it easier on anyone else who finds this, here's the complete C# code necessary to create a recurring element.
private static XDocument GenerateBatchInsertXML(string title, DateTime start, DateTime end)
{
// http://thehightechheels.blogspot.com/2012/12/sharepoint-evenet-recurrencedata-xml.html
var recurrence = new XElement("recurrence",
new XElement("rule",
new XElement("firstDayOfWeek", "su"),
new XElement("repeat",
new XElement("daily",
new XAttribute("weekday", "TRUE"))),
new XElement("windowEnd", String.Format("{0:o}", end))));
return new XDocument(
new XElement("Batch",
new XAttribute("OnError", "Continue"),
new XAttribute("DateInUtc", "True"),
new XElement("Method",
new XAttribute("ID", "1"),
new XAttribute("Cmd", "New"),
new XElement("Field", new XAttribute("Name", "Title"), title),
new XElement("Field", new XAttribute("Name", "EventDate"), String.Format("{0:o}", start)),
new XElement("Field", new XAttribute("Name", "EndDate"), String.Format("{0:o}", end)),
new XElement("Field", new XAttribute("Name", "fAllDayEvent"), "1"),
new XElement("Field", new XAttribute("Name", "fRecurrence"), "1"),
new XElement("Field", new XAttribute("Name", "EventType"), "1"),
new XElement("Field", new XAttribute("Name", "UID"), "{" + Guid.NewGuid() + "}"),
new XElement("Field", new XAttribute("Name", "TimeZone"), "0"),
new XElement("Field", new XAttribute("Name", "RecurrenceData"),
new XCData(recurrence.ToString())))));
}

Copy attribute values based on a preceding node attribute with Groovy

I'm trying to do something in SoapUi with Groovy and it's not working.
I have multiple nodes with many attributes and I need to extract the child node attribute based of a parent's attribute
For example:
<library id="82389389">
<book id="123" bookType="SF">
<price id="325" priceValue="5"/>
</book>
<book id="4741" bookType="History">
<price id="12388" priceValue="15"/>
</book>
<book id="2626" bookType="Drama">
<price id="12145" priceValue="40"/>
</book>
</library>
In this XML I need to extract priceValue based on the bookType and use it somewhere else (the order of the book nodes is changing)
I tried this but it doesn't work:
def response = .../library[1]
def i=0
def records = new XmlSlurper().parseText(response)
def size = records.book.size()
for (i=0,i<size,i++)
{
bookType1 = records.book[i].#bookType.first().value().text();
if (bookType1 == 'History')
{
def priceValueBook = records.book[i].price.#priceValue.first().value().text()
log.info priceValueBook
}
}
It's not clear exactly at what point you are trying to do this, but the following would work in SoapUI script step:
context.expand('${test_step#Response#//*:book[#bookType="History"]/*:price/#priceValue}')

Groovy - XmlSlurper - find innermost element

I have the following xml:
<vehicle>
<car>
<price>100</price>
<price>200</price>
</car>
<car>
<price>300</price>
<price>400</price>
</car>
</vehicle>
Given an xml, how can we get the innermost elements (in this case, all the<price> elements)?
Assuming you have the xml in a String xml, you should be able to do:
List prices = new XmlSlurper().parseText( xml ).car.price*.text()​​
thanks Tim for the answer. I just figured out the following works too. And is more generic:
def document = slurper.parseText(xml)
def prices = document.'**'.findAll { it.children().size() == 0 }
May I suggest you next variant:
def vehicle = new XmlSlurper().parseText(xmlString)
vehicle.car.price.each {println "car's price:"+it}

Resources