public Metadata() { ShowDisplay = true; ShowEditor = true; rules = new List<IRule>(); properties = new PropertiesMetadata(); }
public void SetProperty <T>(string name, T value) { var p = PropertiesMetadata.FirstOrDefault(v => v.Name == name); if (p != null) { // Type should match if (p.Type != value.GetType()) { throw new InvalidCastException(); } } else { if (AllowDynamicProperties) { p = new DynamicPropertyMetadata(name, value.GetType()); p.SaveTypeInfo = true; PropertiesMetadata.Add(p); } else { throw new InvalidPropertyException(); } } Dictionary[name] = value; RaisePropertyChanged(name); }
public string Save() { var sb = new StringBuilder(); using (var xw = XmlWriter.Create(sb, new XmlWriterSettings { OmitXmlDeclaration = true, ConformanceLevel = ConformanceLevel.Fragment, Indent = true })) { foreach (var o in Dictionary) { var propertyDefinition = PropertiesMetadata.Single(x => x.Name == o.Key); if ((propertyDefinition.Options & DynamicPropertyMetadataOptions.Save) == DynamicPropertyMetadataOptions.None) { continue; } var s = new DataContractSerializer(o.Value.GetType(), null); xw.WriteStartElement(o.Key); if (propertyDefinition.SaveTypeInfo) { xw.WriteAttributeString("t", GetTypeFullName(propertyDefinition.Type)); } object content = o.Value; if (content is DateTime) { content = DateTime.SpecifyKind((DateTime)content, DateTimeKind.Unspecified); } if (ShouldWriteContent(o.Value.GetType())) { s.WriteObjectContent(xw, content); } else { s.WriteObject(xw, content); } xw.WriteEndElement(); } } return(sb.ToString()); }
public void Load(string xml) { var root = XElement.Parse("<a>" + xml + "</a>"); Dictionary.Clear(); var b = new StringBuilder(); foreach (var element in root.Elements()) { Type type = null; var typeAttribute = element.Attribute("t"); if (typeAttribute != null) { type = GetType(typeAttribute.Value); } else { var dynamicPropertyMetadata = PropertiesMetadata.FirstOrDefault(x => x.Name == element.Name.LocalName); if (dynamicPropertyMetadata == null) { throw new InvalidPropertyException(); } type = dynamicPropertyMetadata.Type; } var s = new DataContractSerializer(type); using (var reader = ShouldWriteContent(type) ? element.CreateReader() : element.Elements().Single().CreateReader()) { var obj = s.ReadObject(reader, false); SetProperty(element.Name.LocalName, obj); } } RefreshProxy(); }
public T GetProperty <T>(string name) { object value; if (Dictionary.TryGetValue(name, out value)) { return((T)value); } var p = PropertiesMetadata.FirstOrDefault(v => v.Name == name); if (p != null) { return((T)(p.Type.IsValueType ? Activator.CreateInstance(p.Type) : null)); } if (AllowDynamicProperties) { return(default(T)); } throw new InvalidPropertyException(); }
public DocumentBuilder(System.Type clazz, Analyzer defaultAnalyzer, IDirectoryProvider[] directoryProviders, IIndexShardingStrategy shardingStrategy) { analyzer = new ScopedAnalyzer(); beanClass = clazz; this.directoryProviders = directoryProviders; this.shardingStrategy = shardingStrategy; if (clazz == null) throw new AssertionFailure("Unable to build a DocumemntBuilder with a null class"); rootPropertiesMetadata = new PropertiesMetadata(); rootPropertiesMetadata.boost = GetBoost(clazz); rootPropertiesMetadata.analyzer = defaultAnalyzer; Set<System.Type> processedClasses = new HashedSet<System.Type>(); processedClasses.Add(clazz); InitializeMembers(clazz, rootPropertiesMetadata, true, string.Empty, processedClasses); //processedClasses.remove( clazz ); for the sake of completness analyzer.GlobalAnalyzer = rootPropertiesMetadata.analyzer; if (idKeywordName == null) throw new SearchException("No document id for: " + clazz.Name); }
private void InitializeMembers( System.Type clazz, PropertiesMetadata propertiesMetadata, bool isRoot, String prefix, ISet<System.Type> processedClasses) { IList<System.Type> hierarchy = new List<System.Type>(); System.Type currClass = clazz; do { hierarchy.Add(currClass); currClass = currClass.BaseType; // NB Java stops at null we stop at object otherwise we process the class twice // We also need a null test for things like ISet which have no base class/interface } while (currClass != null && currClass != typeof(object)); for (int index = hierarchy.Count - 1; index >= 0; index--) { currClass = hierarchy[index]; /** * Override the default analyzer for the properties if the class hold one * That's the reason we go down the hierarchy */ // NB Must cast here as we want to look at the type's metadata Analyzer localAnalyzer = GetAnalyzer(currClass as MemberInfo); if (localAnalyzer != null) { propertiesMetadata.analyzer = localAnalyzer; } // Check for any ClassBridges List<ClassBridgeAttribute> classBridgeAnn = AttributeUtil.GetClassBridges(currClass); if (classBridgeAnn != null) { // Ok, pick up the parameters as well AttributeUtil.GetClassBridgeParameters(currClass, classBridgeAnn); // Now we can process the class bridges foreach (ClassBridgeAttribute cb in classBridgeAnn) { BindClassAnnotation(prefix, propertiesMetadata, cb); } } // NB As we are walking the hierarchy only retrieve items at this level PropertyInfo[] propertyInfos = currClass.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); foreach (PropertyInfo propertyInfo in propertyInfos) { InitializeMember(propertyInfo, propertiesMetadata, isRoot, prefix, processedClasses); } FieldInfo[] fields = clazz.GetFields(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); foreach (FieldInfo fieldInfo in fields) { InitializeMember(fieldInfo, propertiesMetadata, isRoot, prefix, processedClasses); } } }
private void InitializeMember( MemberInfo member, PropertiesMetadata propertiesMetadata, bool isRoot, String prefix, ISet<System.Type> processedClasses) { DocumentIdAttribute documentIdAnn = AttributeUtil.GetDocumentId(member); if (documentIdAnn != null) { if (isRoot) { if (idKeywordName != null) { throw new AssertionFailure("Two document id assigned: " + idKeywordName + " and " + documentIdAnn.Name ?? "'Unknown'"); } idKeywordName = prefix + documentIdAnn.Name; IFieldBridge fieldBridge = BridgeFactory.GuessType(member); if (fieldBridge is ITwoWayFieldBridge) { idBridge = (ITwoWayFieldBridge)fieldBridge; } else { throw new SearchException("Bridge for document id does not implement TwoWayFieldBridge: " + member.Name); } idBoost = GetBoost(member); SetAccessible(member); idGetter = member; } else { // Component should index their document id SetAccessible(member); propertiesMetadata.fieldGetters.Add(member); string fieldName = prefix + BinderHelper.GetAttributeName(member, documentIdAnn.Name); propertiesMetadata.fieldNames.Add(fieldName); propertiesMetadata.fieldStore.Add(GetStore(Attributes.Store.Yes)); propertiesMetadata.fieldIndex.Add(GetIndex(Index.UnTokenized)); propertiesMetadata.fieldBridges.Add(BridgeFactory.GuessType(member)); // Property > entity analyzer - no field analyzer Analyzer memberAnalyzer = GetAnalyzer(member) ?? propertiesMetadata.analyzer; if (memberAnalyzer == null) { throw new NotSupportedException("Analyzer should not be undefined"); } analyzer.AddScopedAnalyzer(fieldName, memberAnalyzer); } } List<FieldAttribute> fieldAttributes = AttributeUtil.GetFields(member); if (fieldAttributes != null) { foreach (FieldAttribute fieldAnn in fieldAttributes) { BindFieldAnnotation(member, propertiesMetadata, prefix, fieldAnn); } } IndexedEmbeddedAttribute embeddedAttribute = AttributeUtil.GetAttribute<IndexedEmbeddedAttribute>(member); if (embeddedAttribute != null) { int oldMaxLevel = maxLevel; int potentialLevel = embeddedAttribute.Depth + level; if (potentialLevel < 0) { potentialLevel = int.MaxValue; } maxLevel = potentialLevel > maxLevel ? maxLevel : potentialLevel; level++; System.Type elementType = embeddedAttribute.TargetElement ?? GetMemberTypeOrGenericArguments(member); if (maxLevel == int.MaxValue && processedClasses.Contains(elementType)) { throw new SearchException( string.Format( "Circular reference, Duplicate use of {0} in root entity {1}#{2}", elementType.FullName, beanClass.FullName, BuildEmbeddedPrefix(prefix, embeddedAttribute, member))); } if (level <= maxLevel) { processedClasses.Add(elementType); // push SetAccessible(member); propertiesMetadata.embeddedGetters.Add(member); PropertiesMetadata metadata = new PropertiesMetadata(); propertiesMetadata.embeddedPropertiesMetadata.Add(metadata); metadata.boost = GetBoost(member); // property > entity analyzer metadata.analyzer = GetAnalyzer(member) ?? propertiesMetadata.analyzer; string localPrefix = BuildEmbeddedPrefix(prefix, embeddedAttribute, member); InitializeMembers(elementType, metadata, false, localPrefix, processedClasses); /** * We will only index the "expected" type but that's OK, HQL cannot do downcasting either */ // ayende: because we have to deal with generic collections here, we aren't // actually using the element type to determine what the value is, since that // was resolved to the element type of the possible collection Type actualFieldType = GetMemberTypeOrGenericCollectionType(member); if (actualFieldType.IsArray) { propertiesMetadata.embeddedContainers.Add(Container.Array); } else if (typeof(IDictionary).IsAssignableFrom(actualFieldType) || typeof(IDictionary<,>).IsAssignableFrom(actualFieldType)) { propertiesMetadata.embeddedContainers.Add(Container.Map); } else if (typeof(ICollection).IsAssignableFrom(actualFieldType)) { propertiesMetadata.embeddedContainers.Add(Container.Collection); } else if (typeof(IEnumerable).IsAssignableFrom(actualFieldType)) { // NB We only see ISet as IEnumerable propertiesMetadata.embeddedContainers.Add(Container.Collection); } else { propertiesMetadata.embeddedContainers.Add(Container.Object); } processedClasses.Remove(actualFieldType); // pop } else if (logger.IsDebugEnabled) { string localPrefix = BuildEmbeddedPrefix(prefix, embeddedAttribute, member); logger.Debug("Depth reached, ignoring " + localPrefix); } level--; maxLevel = oldMaxLevel; // set back the old max level } ContainedInAttribute containedInAttribute = AttributeUtil.GetAttribute<ContainedInAttribute>(member); if (containedInAttribute != null) { SetAccessible(member); propertiesMetadata.containedInGetters.Add(member); } }
private void BindFieldAnnotation(MemberInfo member, PropertiesMetadata propertiesMetadata, string prefix, FieldAttribute fieldAnn) { SetAccessible(member); propertiesMetadata.fieldGetters.Add(member); string fieldName = prefix + BinderHelper.GetAttributeName(member, fieldAnn.Name); propertiesMetadata.fieldNames.Add(prefix + fieldAnn.Name); propertiesMetadata.fieldStore.Add(GetStore(fieldAnn.Store)); propertiesMetadata.fieldIndex.Add(GetIndex(fieldAnn.Index)); propertiesMetadata.fieldBridges.Add(BridgeFactory.GuessType(member)); // Field > property > entity analyzer Analyzer localAnalyzer = (GetAnalyzer(fieldAnn.Analyzer) ?? GetAnalyzer(member)) ?? propertiesMetadata.analyzer; if (localAnalyzer == null) { throw new NotSupportedException("Analyzer should not be undefined"); } analyzer.AddScopedAnalyzer(fieldName, localAnalyzer); }
private void BindClassAnnotation(string prefix, PropertiesMetadata propertiesMetadata, ClassBridgeAttribute ann) { // TODO: Name should be prefixed - NB is this still true? string fieldName = prefix + ann.Name; propertiesMetadata.classNames.Add(fieldName); propertiesMetadata.classStores.Add(GetStore(ann.Store)); propertiesMetadata.classIndexes.Add(GetIndex(ann.Index)); propertiesMetadata.classBridges.Add(BridgeFactory.ExtractType(ann)); propertiesMetadata.classBoosts.Add(ann.Boost); Analyzer classAnalyzer = GetAnalyzer(ann.Analyzer) ?? propertiesMetadata.analyzer; if (classAnalyzer == null) { throw new NotSupportedException("Analyzer should not be undefined"); } analyzer.AddScopedAnalyzer(fieldName, classAnalyzer); }
private static void ProcessFieldsForProjection(PropertiesMetadata metadata, String[] fields, Object[] result, Document document) { int nbrFoEntityFields = metadata.fieldNames.Count; for (int index = 0; index < nbrFoEntityFields; index++) { PopulateResult(metadata.fieldNames[index], metadata.fieldBridges[index], metadata.fieldStore[index], fields, result, document ); } int nbrOfEmbeddedObjects = metadata.embeddedPropertiesMetadata.Count; for (int index = 0; index < nbrOfEmbeddedObjects; index++) { // there is nothing we can do for collections if (metadata.embeddedContainers[index] == Container.Object) { ProcessFieldsForProjection(metadata.embeddedPropertiesMetadata[index], fields, result, document); } } }
private static void ProcessContainedIn(Object instance, List<LuceneWork> queue, PropertiesMetadata metadata, ISearchFactoryImplementor searchFactoryImplementor) { for (int i = 0; i < metadata.containedInGetters.Count; i++) { MemberInfo member = metadata.containedInGetters[i]; object value = GetMemberValue(instance, member); if (value == null) continue; Array array = value as Array; if (array != null) { foreach (object arrayValue in array) { // Highly inneficient but safe wrt the actual targeted class, e.g. polymorphic items in the array System.Type valueType = NHibernateUtil.GetClass(arrayValue); if (valueType == null || !searchFactoryImplementor.DocumentBuilders.ContainsKey(valueType)) { continue; } ProcessContainedInValue(arrayValue, queue, valueType, searchFactoryImplementor.DocumentBuilders[valueType], searchFactoryImplementor); } } else if (typeof(IEnumerable).IsAssignableFrom(value.GetType())) { // NB We only see ISet and IDictionary`2 as IEnumerable IEnumerable collection = value as IEnumerable; if (typeof(IDictionary).IsAssignableFrom(value.GetType())) { collection = ((IDictionary) value).Values; } if (collection == null) { continue; } foreach (object collectionValue in collection) { // Highly inneficient but safe wrt the actual targeted class, e.g. polymorphic items in the array System.Type valueType = NHibernateUtil.GetClass(collectionValue); if (valueType == null || !searchFactoryImplementor.DocumentBuilders.ContainsKey(valueType)) { continue; } ProcessContainedInValue(collectionValue, queue, valueType, searchFactoryImplementor.DocumentBuilders[valueType], searchFactoryImplementor); } } else { System.Type valueType = NHibernateUtil.GetClass(value); if (valueType == null || !searchFactoryImplementor.DocumentBuilders.ContainsKey(valueType)) { continue; } ProcessContainedInValue(value, queue, valueType, searchFactoryImplementor.DocumentBuilders[valueType], searchFactoryImplementor); } } //an embedded cannot have a useful @ContainedIn (no shared reference) //do not walk through them }
private static void BuildDocumentFields(Object instance, Document doc, PropertiesMetadata propertiesMetadata) { if (instance == null) { return; } object unproxiedInstance = Unproxy(instance); for (int i = 0; i < propertiesMetadata.classBridges.Count; i++) { IFieldBridge fb = propertiesMetadata.classBridges[i]; try { fb.Set(propertiesMetadata.classNames[i], unproxiedInstance, doc, propertiesMetadata.classStores[i], propertiesMetadata.classIndexes[i], propertiesMetadata.classBoosts[i]); } catch (Exception e) { logger.Error( string.Format(CultureInfo.InvariantCulture, "Error processing class bridge for {0}", propertiesMetadata.classNames[i]), e); } } for (int i = 0; i < propertiesMetadata.fieldNames.Count; i++) { try { MemberInfo member = propertiesMetadata.fieldGetters[i]; Object value = GetMemberValue(unproxiedInstance, member); propertiesMetadata.fieldBridges[i].Set( propertiesMetadata.fieldNames[i], value, doc, propertiesMetadata.fieldStore[i], propertiesMetadata.fieldIndex[i], GetBoost(member)); } catch (Exception e) { logger.Error( string.Format(CultureInfo.InvariantCulture, "Error processing field bridge for {0}.{1}", unproxiedInstance.GetType().FullName, propertiesMetadata.fieldNames[i]), e); } } for (int i = 0; i < propertiesMetadata.embeddedGetters.Count; i++) { MemberInfo member = propertiesMetadata.embeddedGetters[i]; Object value = GetMemberValue(unproxiedInstance, member); //TODO handle boost at embedded level: already stored in propertiesMedatada.boost if (value == null) { continue; } PropertiesMetadata embeddedMetadata = propertiesMetadata.embeddedPropertiesMetadata[i]; try { switch (propertiesMetadata.embeddedContainers[i]) { case Container.Array: foreach (object arrayValue in value as Array) { BuildDocumentFields(arrayValue, doc, embeddedMetadata); } break; case Container.Collection: // Need to cast down to IEnumerable to support ISet foreach (object collectionValue in value as IEnumerable) { BuildDocumentFields(collectionValue, doc, embeddedMetadata); } break; case Container.Map: foreach (object collectionValue in (value as IDictionary).Values) { BuildDocumentFields(collectionValue, doc, embeddedMetadata); } break; case Container.Object: BuildDocumentFields(value, doc, embeddedMetadata); break; default: throw new NotSupportedException("Unknown embedded container: " + propertiesMetadata.embeddedContainers[i]); } } catch (NullReferenceException) { logger.Error(string.Format("Null reference whilst processing {0}.{1}, container type {2}", instance.GetType().FullName, member.Name, propertiesMetadata.embeddedContainers[i])); } } }