I have the below document:
<Ships>
<Class name = "Kongo" >
<Ship name "Kongo" launched = "1913" />
<Ship name = "Hiei" launched = "1914"/>
<Ship name = "Haruna" launched = "1915" />
</Class>
<Class name = "North Carolina">
<Ship name = "Washington" launched= "1941"/>
</Class>
</Ships>
I need to find the years in which ships having the same name as their class were
launched. Which should be
/Ships/Class/Ship[..]/#launched
the '...' part has been omitted as it should be a condition that specifies where the ship name equals to its class name. Does anyone know how to refer to a higher level element's attribute? The query should return '1913'
Ships/Class/Ship[#name = ../#name]/#launched
Related
I am trying to create a snippet that creates a field and a property for that field.
I want to use pascalCase for the field and CamelCase for the property, I want the snippet to do this automatically. I can do it if I create two different literals and manually write the name for the field and the name for the property, is there a way to automatically "create" the name for the property with capital first letter with the name taken from the name of the field?
This is my current snippet code:
<CodeSnippet Format="1.0.0">
<Header>
<Title>Property etc</Title>
<Shortcut>fprop</Shortcut>
</Header>
<Snippet>
<Declarations>
<Literal>
<ID>type</ID>
<Default>int</Default>
</Literal>
<Literal>
<ID>name</ID>
<Default>propertyName</Default>
</Literal>
</Declarations>
<Code Language="csharp">
<![CDATA[private $type$ $name$;
public $type$ $name$ <<<<--- this $name$ must have its first letter capitalized in the final result
{
get
{
return this.$name$;
}
set
{
this.$name$ = value;
}
}
$end$]]>
</Code>
</Snippet>
This is the expected result:
private int propertyName;
public int PropertyName
{
get
{
return this.propertyName;
}
set
{
this.propertyName = value;
}
}
If I use a different name for the field, for example "someFieldName" the name for the property should automatically become SomeFieldName (at the time of the snippet creation of course)
I know that I can do this if I use two separate Literals, but then I have to manually write the name for the field and then write the name for the property aswell, I want to avoid writing the property name manually.
It can be done with ReSharper.
Using Template Explorer ("Extensions->ReSharper->Tools->Templates Explorer...")
create new template
private $TYPE$ $FIELD_NAME$;
public $TYPE$ $PROPERTY_NAME$
{
get
{
return this.$FIELD_NAME$;
}
set
{
this.$FIELD_NAME$ = value;
}
}
Template settings:
uncheck Reformat
Parameters settings:
PROPERTY_Name set as first element, Editable, Suggest name for a variable
TYPE set as second element, MO-2, Suggest type for a new variable
FIELD_NAME set as third element, Not Editable, Value of another variable with first character in lower case and select PROPERTY_NAME
I have a provider, wich index stock for product for every unit, this way:
for (Map.Entry<B2BUnitModel, Integer> unit : stockByUnit.entrySet() )
{
document.addField(indexedProperty, hasStock(unit.getValue()), unitUid(unit.getKey()));
}
so this is result after index in solr:
"localStockForUnt_001_boolean": true,
"localStockForUnt_002_boolean": true,
where localStockForUnt is SolrIndexedProperty, 001 and 002 are the units and true or false are the indexed value.
this is the impex to create it:
INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)`[unique=true];name[unique=true];type(code);sortableType(code);currency[default=false];localized[default=false];multiValue[default=false];useForSpellchecking[default=false];useForAutocomplete[default=false];fieldValueProvider;valueProviderParameter`
;$solrIndexedType; localStockForUnt ;boolean ; ; ; ; ; ; ;myResolver;
so I added it inside the 'sort' called 'relevance' in hmc, this 'sort' just have this field in hmc.
My doubt is, how can I set to it sort my result using for example localStockForUnt_002_boolean?
I did set sort in controller manually to test, I did set it to "relevance", but since the provider of field used in relevance (localStockForUnt) index two diferent informations, how can I select which one to use?
Actually what you are trying to do here was already been initiated and used in several cases by Hybris, for example:
localized properties like the name, indexed as name_en_string.
properties with currency like price is indexed as priceValue_eur_double and also used for Sort.
For :priceValue_eur_double | For : localStockForUnt_001_boolean.
priceValue is the field's name | localStockForUnt is the field's name.
euris the field qualifier | 001 is the field qualifier.
double is the field type | boolean is the field type.
So your case here is not different than these two examples, hence you need just to know how to use what's already exists.
Actually nothing magical about how these two examples works!
First of all, add new boolean attribute to SolrIndexedPropertyModel let's call it isB2bUnit :
<!-- add this to your *-items.xml -->
<itemtype code="SolrIndexedProperty" autocreate="false" generate="false">
<attributes>
<attribute qualifier="isB2bUnit" type="java.lang.boolean">
<persistence type="property" />
<!-- i would prefer to add a default value here : FALSE -->
</attribute>
</attributes>
</itemtype>
Next you have to add the same boolean attribute in the IndexedProperty dto :
<!-- add this to your *-beans.xml -->
<bean class="de.hybris.platform.solrfacetsearch.config.IndexedProperty">
<property name="isB2bUnit" type="boolean"/>
</bean>
Then you need to override DefaultIndexedPropertyPopulator it's the responsible for converting from SolrIndexedProperty to IndexedProperty:
public class MyIndexedPropertyPopulator extends DefaultIndexedPropertyPopulator {
#Override
public void populate(SolrIndexedPropertyModel source, IndexedProperty target) throws ConversionException {
super.populate(source, target);
//add this line
target.setIsB2bUnit(source.getIsB2bUnit());
}
}
Register the propulator into spring.
<!-- add this to your *-spring.xml -->
<alias name="myIndexedPropertyPopulator" alias="indexedPropertyPopulator" />
<bean id="myIndexedPropertyPopulator" class="com.foo.bar.MyIndexedPropertyPopulator" parent="defaultIndexedPropertyPopulator" />
The idea is to hook into this method DefaultFieldNameTranslator.translateFromProperty(...) and force it to add your specific fieldQualifier which is b2bUnit.code to the fieldName if the isB2bUnit of the Indexedproperty is TRUE.
The original DefaultFieldNameTranslator.translateFromProperty(...) is like this :
protected String translateFromProperty(SearchQuery searchQuery, IndexedProperty indexedProperty, FieldType fieldType) {
//...
if(qualifierProvider != null && qualifierProvider.canApply(indexedProperty)) {
Qualifier qualifier = qualifierProvider.getCurrentQualifier();
fieldQualifier = qualifier != null?qualifier.toFieldQualifier():null;
} else if(indexedProperty.isLocalized()) {
fieldQualifier = searchQuery.getLanguage();
} else if(indexedProperty.isCurrency()) {
fieldQualifier = searchQuery.getCurrency();
}
//you have to add your else if here!!!
return this.fieldNameProvider.getFieldName(indexedProperty, fieldQualifier, fieldType);
}
So create MyFieldNameTranslator that extends from DefaultFieldNameTranslator and override translateFromProperty(...).
Note: SomeB2bUnitService this service is not real but it should be able to return the current b2bUnit.
public class MyFieldNameTranslator extends DefaultFieldNameTranslator {
//To be injected!!
private SomeB2bUnitService someB2bUnitService;
#Override
protected String translateFromProperty(SearchQuery searchQuery, IndexedProperty indexedProperty, FieldType fieldType) {
//...
//...
else if(indexedProperty.getIsB2bUnit()) {
fieldQualifier = someB2bUnitService.getCurrentB2bUnit().getCode();
}
return this.fieldNameProvider.getFieldName(indexedProperty, fieldQualifier, fieldType);
}
}
Register the Translator into Spring :
<!-- add this to your *-spring.xml -->
<alias name="myfieldNameTranslator" alias="fieldNameTranslator" />
<bean id="myfieldNameTranslator" class="com.foo.bar.MyFieldNameTranslator" parent="defaultfieldNameTranslator">
<property name="someB2bUnitService" ref="someB2bUnitService" />
</bean>
Edit : now all what you have to do is to set isB2bUnit to true for localStockForUnt:
INSERT_UPDATE SolrIndexedProperty;solrIndexedType(identifier)[unique=true] ;name[unique=true] ;type(code) ;isB2bUnit
;$solrIndexedType ;localStockForUnt ;boolean ;true
Note : that some classes and beans may have been changed between Hybris versions but the concept will remains the same.
I have this XML data
<Address Location="ABC">
<Add Location="XYZ1" street="street1" />
<Add Location="VZC" street="street1" />
</Address>
I want to find out the value of <add> --> street which is street1
I have tried it as below, not getting the result
var q = from res in xmlDoc.Descendants("Address")
where res.Attribute("Location").Value == "ABC"
&& res.Element("Add").Attribute("Location").Value == "VZC"
select new
{
streetadd= res.Element("Add").Attribute("street").Value,
};
Please someone suggest how to check the condition for child element in this case.
Try this:
var query = from res in xmlDoc.Descendants("Address")
where res.Attribute("Location").Value == "ABC"
from child in res.Elements("Add")
where child.Attribute("Location").Value == "VZC"
select new
{
streetadd = child.Attribute("street").Value
};
I've got class, let it be Foo:
public class Foo
{
...
protected MyCollection<Detail> _details
public virtual MyCollection<Detail> Details
{
get { return _details ?? new MyCollection<Details>(); }
set { _details = value; ... }
}
...
}
public class Detail {...}
When I do LINQ query:
var q = session.Query<Foo>().Select(foo => new Foo( property1 = foo.property1, ... );
...
q.ToList();
I've got NULL in _details field, and when I access to Details to get all Lazy details, of course I get new MyCollection(), but not IPersistentBag (or else, IPersistentCollection).
So How can I manually create proxy collection (I've got session / sessionFactory references)?
[ Added ] here is the mappings (on Foo):
<bag name="Details" lazy="true" collection-type="NHibernateDataService.DetailBag`1[[DataObjects.Detail, DataObjects]], NHibernateDataService" cascade="all-delete-orphan" fetch="select" batch-size="1" access="property" inverse="true">
<key column="`Master`" />
<one-to-many class="DataObjects.Detail" />
</bag>
Thank you!
MyCollection can't be mapped to IPersistentBag, unless, of course, you implement that interface on MyCollection (and probably set the mapping type explicitly??)...
A more standard approach is to set the "collection-type" property on the bag mapping to a custom type - an implementation of IUserCollectionType, which you can choose to make a base class that MyCollection derives from.
HI
I have an example document that looks like
<ItemEntry>
<PurchaseDate>2010-03-18T20:36:32.81108+13:00</PurchaseDate>
<StoreGUID>0a0324ad-5f99-486a-a2d0-870bc6991e9f</StoreGUID>
<ExpiryDate />
<CardID>111111</CardID>
<PurchaseAmount>0</PurchaseAmount>
<RedeemedAmount />
<EntryType>1</EntryType>
<RedeemedDate />
<SalesAssistantID>0</SalesAssistantID>
</ItemEntry>
As you can see there are couple of elements ExpiryDate and RedeemedDate are are empty.
var q = from c in xml.Elements("ItemEntry")
select new mdDetail {
PurchaseDate = (DateTime)c.Element("PurchaseDate"),
StoreGUID = (Guid)c.Element("StoreGUID"),
ExpiryDate = (DateTime?)c.Element("ExpiryDate")??DateTime.MinValue,
CardID = (int)c.Element("CardID"),
PurchaseAmount = (double)c.Element("PurchaseAmount"),
RedeemedAmount = (double?)c.Element("RedeemedAmount"),
EntryType = (int)c.Element("EntryType"),
RedeemedDate = (DateTime?)c.Element("RedeemedDate") ??DateTime.MinValue,
SalesAssistantID = (int)c.Element("SalesAssistantID"),
}
;
foreach (var item in q)
{
}
I am not sure how to deal with the null element value,
I have tried ??DateTime.MinValue and ??null however both give me a "
String was not recognized as a valid DateTime." error.
Any suggestions?
Thank you
ExpiryDate = String.IsNullOrEmpty((string)c.Element("ExpiryDate"))?
DateTime.MinValue : DateTime.Parse((string)c.Element("ExpiryDate"))
"You could also use null instead of DateTime.MinValue if ExpireyDate is
declared to be nullable"
#Gabe, you can't just use null - you need to use (DateTime?)null because the compiler won't know how to convert null into a DateTime object
So if you want the value to just be a blank (null) this would be the final code:
ExpiryDate = String.IsNullOrEmpty(c.Element("ExpiryDate").Value)?
(DateTime?)null : DateTime.Parse(c.Element("ExpiryDate").Value)
Assuming DateTime is a declared a nullable (DateTime?)