public override void Run(EPServiceProvider epService) { // Note that XPath Node results when transposed must be queried by XPath that is also absolute. // For example: "nested1" => "/n0:simpleEvent/n0:nested1" results in a Node. // That result Node's "prop1" => "/n0:simpleEvent/n0:nested1/n0:prop1" and "/n0:nested1/n0:prop1" does NOT result in a value. // Therefore property transposal is disabled for Property-XPath expressions. var eventTypeMeta = new ConfigurationEventTypeXMLDOM(); eventTypeMeta.RootElementName = "simpleEvent"; string schemaUri = SupportContainer.Instance.ResourceManager().ResolveResourceURL(CLASSLOADER_SCHEMA_URI).ToString(); eventTypeMeta.SchemaResource = schemaUri; eventTypeMeta.IsXPathPropertyExpr = true; // <== note this eventTypeMeta.AddNamespacePrefix("ss", "samples:schemas:simpleSchema"); epService.EPAdministrator.Configuration.AddEventType("TestXMLSchemaType", eventTypeMeta); // note class not a fragment EPStatement stmtInsert = epService.EPAdministrator.CreateEPL("insert into MyNestedStream select nested1 from TestXMLSchemaType#lastevent"); EPAssertionUtil.AssertEqualsAnyOrder(new EventPropertyDescriptor[] { new EventPropertyDescriptor("nested1", typeof(XmlNode), null, false, false, false, false, false), }, stmtInsert.EventType.PropertyDescriptors); SupportEventTypeAssertionUtil.AssertConsistency(stmtInsert.EventType); EventType type = ((EPServiceProviderSPI)epService).EventAdapterService.GetEventTypeByName("TestXMLSchemaType"); SupportEventTypeAssertionUtil.AssertConsistency(type); Assert.IsNull(type.GetFragmentType("nested1")); Assert.IsNull(type.GetFragmentType("nested1.nested2")); SupportXML.SendDefaultEvent(epService.EPRuntime, "ABC"); SupportEventTypeAssertionUtil.AssertConsistency(stmtInsert.First()); }
private void RunAssertionTypeValidProp(EPServiceProvider epService, string typeName, object underlying) { EventType eventType = epService.EPAdministrator.Configuration.GetEventType(typeName); var expectedType = new[] { new object[] { "indexed", typeof(string[]), null, null }, new object[] { "mapped", typeof(StringMap), null, null } }; SupportEventTypeAssertionUtil.AssertEventTypeProperties(expectedType, eventType, SupportEventTypeAssertionEnumExtensions.GetSetWithFragment()); EPAssertionUtil.AssertEqualsAnyOrder(new[] { "indexed", "mapped" }, eventType.PropertyNames); Assert.IsNotNull(eventType.GetGetter("mapped")); Assert.IsNotNull(eventType.GetGetter("mapped('a')")); Assert.IsNotNull(eventType.GetGetter("indexed")); Assert.IsNotNull(eventType.GetGetter("indexed[0]")); Assert.IsTrue(eventType.IsProperty("mapped")); Assert.IsTrue(eventType.IsProperty("mapped('a')")); Assert.IsTrue(eventType.IsProperty("indexed")); Assert.IsTrue(eventType.IsProperty("indexed[0]")); Assert.AreEqual(typeof(StringMap), eventType.GetPropertyType("mapped")); Assert.AreEqual(typeof(string), eventType.GetPropertyType("mapped('a')")); Assert.AreEqual(typeof(string[]), eventType.GetPropertyType("indexed")); Assert.AreEqual(typeof(string), eventType.GetPropertyType("indexed[0]")); Assert.AreEqual(new EventPropertyDescriptor("indexed", typeof(string[]), typeof(string), false, false, true, false, false), eventType.GetPropertyDescriptor("indexed")); Assert.AreEqual(new EventPropertyDescriptor("mapped", typeof(StringMap), typeof(string), false, false, false, true, false), eventType.GetPropertyDescriptor("mapped")); Assert.IsNull(eventType.GetFragmentType("indexed")); Assert.IsNull(eventType.GetFragmentType("mapped")); }
public void TestExpressionSimpleXPathGetter() { var eventTypeMeta = new ConfigurationEventTypeXMLDOM(); eventTypeMeta.RootElementName = "simpleEvent"; var schemaUri = ResourceManager.ResolveResourceURL(CLASSLOADER_SCHEMA_URI).ToString(); eventTypeMeta.SchemaResource = schemaUri; eventTypeMeta.IsXPathPropertyExpr = true; // <== note this eventTypeMeta.AddNamespacePrefix("ss", "samples:schemas:simpleSchema"); _epService.EPAdministrator.Configuration.AddEventType("TestXMLSchemaType", eventTypeMeta); // note class not a fragment var stmtInsert = _epService.EPAdministrator.CreateEPL("insert into MyNestedStream select nested1 from TestXMLSchemaType#lastevent"); EPAssertionUtil.AssertEqualsAnyOrder(new EventPropertyDescriptor[] { new EventPropertyDescriptor("nested1", typeof(XmlNode), null, false, false, false, false, false), }, stmtInsert.EventType.PropertyDescriptors); SupportEventTypeAssertionUtil.AssertConsistency(stmtInsert.EventType); EventType type = ((EPServiceProviderSPI)_epService).EventAdapterService.GetEventTypeByName("TestXMLSchemaType"); SupportEventTypeAssertionUtil.AssertConsistency(type); Assert.IsNull(type.GetFragmentType("nested1")); Assert.IsNull(type.GetFragmentType("nested1.nested2")); SupportXML.SendDefaultEvent(_epService.EPRuntime, "ABC"); SupportEventTypeAssertionUtil.AssertConsistency(stmtInsert.First()); }
private void TryAssertionMapTranspose(EPServiceProvider epService, EventRepresentationChoice eventRepresentationEnum) { var innerTypeOne = new Dictionary <string, object>(); innerTypeOne.Put("i1", typeof(int)); var innerTypeTwo = new Dictionary <string, object>(); innerTypeTwo.Put("i2", typeof(int)); var outerType = new Dictionary <string, object>(); outerType.Put("one", "T1"); outerType.Put("two", "T2"); epService.EPAdministrator.Configuration.AddEventType("T1", innerTypeOne); epService.EPAdministrator.Configuration.AddEventType("T2", innerTypeTwo); epService.EPAdministrator.Configuration.AddEventType("OuterType", outerType); // create window string stmtTextCreate = eventRepresentationEnum.GetAnnotationText() + " create window MyWindowMT#keepall as select one, two from OuterType"; EPStatement stmtCreate = epService.EPAdministrator.CreateEPL(stmtTextCreate); Assert.IsTrue(eventRepresentationEnum.MatchesClass(stmtCreate.EventType.UnderlyingType)); var listenerWindow = new SupportUpdateListener(); stmtCreate.Events += listenerWindow.Update; EPAssertionUtil.AssertEqualsAnyOrder(stmtCreate.EventType.PropertyNames, new string[] { "one", "two" }); EventType eventType = stmtCreate.EventType; Assert.AreEqual("T1", eventType.GetFragmentType("one").FragmentType.Name); Assert.AreEqual("T2", eventType.GetFragmentType("two").FragmentType.Name); // create insert into string stmtTextInsertOne = "insert into MyWindowMT select one, two from OuterType"; epService.EPAdministrator.CreateEPL(stmtTextInsertOne); var innerDataOne = new Dictionary <string, object>(); innerDataOne.Put("i1", 1); var innerDataTwo = new Dictionary <string, object>(); innerDataTwo.Put("i2", 2); var outerData = new Dictionary <string, object>(); outerData.Put("one", innerDataOne); outerData.Put("two", innerDataTwo); epService.EPRuntime.SendEvent(outerData, "OuterType"); EPAssertionUtil.AssertProps(listenerWindow.AssertOneGetNewAndReset(), "one.i1,two.i2".Split(','), new object[] { 1, 2 }); epService.EPAdministrator.DestroyAllStatements(); epService.EPAdministrator.Configuration.RemoveEventType("MyWindowMT", true); }
public static ExprDotEnumerationSourceForProps GetPropertyEnumerationSource(string propertyName, int streamId, EventType streamType, bool allowEnumType, bool disablePropertyExpressionEventCollCache) { var propertyType = streamType.GetPropertyType(propertyName); var typeInfo = EPTypeHelper.SingleValue(propertyType); // assume scalar for now // no enumeration methods, no need to expose as an enumeration if (!allowEnumType) { return(new ExprDotEnumerationSourceForProps(null, typeInfo, streamId, null)); } var fragmentEventType = streamType.GetFragmentType(propertyName); var getter = streamType.GetGetter(propertyName); ExprEvaluatorEnumeration enumEvaluator = null; if (getter != null && fragmentEventType != null) { if (fragmentEventType.IsIndexed) { enumEvaluator = new PropertyExprEvaluatorEventCollection(propertyName, streamId, fragmentEventType.FragmentType, getter, disablePropertyExpressionEventCollCache); typeInfo = EPTypeHelper.CollectionOfEvents(fragmentEventType.FragmentType); } else { // we don't want native to require an eventbean instance enumEvaluator = new PropertyExprEvaluatorEventSingle(streamId, fragmentEventType.FragmentType, getter); typeInfo = EPTypeHelper.SingleEvent(fragmentEventType.FragmentType); } } else { var desc = EventTypeUtility.GetNestablePropertyDescriptor(streamType, propertyName); if (desc != null && desc.IsIndexed && !desc.RequiresIndex && desc.PropertyComponentType != null) { if (propertyType.IsGenericCollection()) { enumEvaluator = new PropertyExprEvaluatorScalarCollection(propertyName, streamId, getter, desc.PropertyComponentType); } else if (propertyType.IsImplementsInterface(typeof(System.Collections.IEnumerable))) { enumEvaluator = new PropertyExprEvaluatorScalarIterable(propertyName, streamId, getter, desc.PropertyComponentType); } else if (propertyType.IsArray) { enumEvaluator = new PropertyExprEvaluatorScalarArray(propertyName, streamId, getter, desc.PropertyComponentType); } else { throw new IllegalStateException("Property indicated indexed-type but failed to find proper collection adapter for use with enumeration methods"); } typeInfo = EPTypeHelper.CollectionOfSingleValue(desc.PropertyComponentType); } } var enumEvaluatorGivenEvent = (ExprEvaluatorEnumerationGivenEvent)enumEvaluator; return(new ExprDotEnumerationSourceForProps(enumEvaluator, typeInfo, streamId, enumEvaluatorGivenEvent)); }
private PropertyResolutionDescriptor FindByPropertyNameExplicitProps(String propertyName, bool obtainFragment) { var index = 0; var foundIndex = 0; var foundCount = 0; EventType streamType = null; for (var i = 0; i < _eventTypes.Length; i++) { if (_eventTypes[i] != null) { var descriptors = _eventTypes[i].PropertyDescriptors; Type propertyType = null; var found = false; FragmentEventType fragmentEventTypeX = null; foreach (var desc in descriptors) { if (desc.PropertyName.Equals(propertyName)) { propertyType = desc.PropertyType; found = true; if (obtainFragment && desc.IsFragment) { fragmentEventTypeX = _eventTypes[i].GetFragmentType(propertyName); } } } if (found) { streamType = _eventTypes[i]; foundCount++; foundIndex = index; // If the property could be resolved from stream 0 then we don't need to look further if ((i == 0) && _isStreamZeroUnambigous) { return(new PropertyResolutionDescriptor(_streamNames[0], _eventTypes[0], propertyName, 0, propertyType, fragmentEventTypeX)); } } } index++; } HandleFindExceptions(propertyName, foundCount, streamType); FragmentEventType fragmentEventType = null; if (obtainFragment) { fragmentEventType = streamType.GetFragmentType(propertyName); } return(new PropertyResolutionDescriptor(_streamNames[foundIndex], _eventTypes[foundIndex], propertyName, foundIndex, streamType.GetPropertyType(propertyName), fragmentEventType)); }
public static object ExtractFragmentTypeIsIndexed(EventPropertyDescriptor desc, EventType eventType) { FragmentEventType fragType = eventType.GetFragmentType(desc.PropertyName); if (fragType == null) { return(null); } return(fragType.IsIndexed); }
private void AssertFragment(String prop, EventType eventType, String fragmentTypeName, bool indexed) { var desc = eventType.GetPropertyDescriptor(prop); Assert.AreEqual(true, desc.IsFragment); var fragment = eventType.GetFragmentType(prop); Assert.AreEqual(fragmentTypeName, fragment.FragmentType.Name); Assert.AreEqual(false, fragment.IsNative); Assert.AreEqual(indexed, fragment.IsIndexed); }
private static void AssertConsistencyRecursive(EventType eventType, ICollection <EventType> alreadySeenTypes) { if (alreadySeenTypes.Contains(eventType)) { return; } alreadySeenTypes.Add(eventType); AssertConsistencyProperties(eventType); // test fragments foreach (var descriptor in eventType.PropertyDescriptors) { var failedMessage = "failed assertion for property '" + descriptor.PropertyName + "' "; if (!descriptor.IsFragment) { Assert.IsNull(eventType.GetFragmentType(descriptor.PropertyName), failedMessage); continue; } var fragment = eventType.GetFragmentType(descriptor.PropertyName); if (!descriptor.RequiresIndex) { Assert.NotNull(fragment, failedMessage); if (fragment.IsIndexed) { Assert.IsTrue(descriptor.IsIndexed); } AssertConsistencyRecursive(fragment.FragmentType, alreadySeenTypes); } else { fragment = eventType.GetFragmentType(descriptor.PropertyName + "[0]"); Assert.NotNull(fragment, failedMessage); Assert.IsTrue(descriptor.IsIndexed); AssertConsistencyRecursive(fragment.FragmentType, alreadySeenTypes); } } }
private static void AssertConsistencyRecursive(EventType eventType, ISet<EventType> alreadySeenTypes) { if (alreadySeenTypes.Contains(eventType)) { return; } alreadySeenTypes.Add(eventType); AssertConsistencyProperties(eventType); // test fragments foreach (EventPropertyDescriptor descriptor in eventType.PropertyDescriptors) { string failedMessage = "failed assertion for property '" + descriptor.PropertyName + "' "; if (!descriptor.IsFragment) { ScopeTestHelper.AssertNull(failedMessage, eventType.GetFragmentType(descriptor.PropertyName)); continue; } FragmentEventType fragment = eventType.GetFragmentType(descriptor.PropertyName); if (!descriptor.RequiresIndex) { ScopeTestHelper.AssertNotNull(failedMessage, fragment); if (fragment.IsIndexed) { ScopeTestHelper.AssertTrue(descriptor.IsIndexed); } AssertConsistencyRecursive(fragment.FragmentType, alreadySeenTypes); } else { fragment = eventType.GetFragmentType(descriptor.PropertyName + "[0]"); ScopeTestHelper.AssertNotNull(failedMessage, fragment); ScopeTestHelper.AssertTrue(descriptor.IsIndexed); AssertConsistencyRecursive(fragment.FragmentType, alreadySeenTypes); } } }
private static void PlanPropertiesMayRecurse( EventType eventType, IList <StmtClassForgeableFactory> additionalForgeables, StatementRawInfo raw, SerdeEventTypeCompileTimeRegistry registry, SerdeCompileTimeResolver resolver) { foreach (var desc in eventType.PropertyDescriptors) { if (!desc.IsFragment) { continue; } var fragmentEventType = eventType.GetFragmentType(desc.PropertyName); if (fragmentEventType == null || registry.EventTypes.ContainsKey(fragmentEventType.FragmentType)) { continue; } PlanRecursive(additionalForgeables, fragmentEventType.FragmentType, raw, registry, resolver); } }
private PropertyResolutionDescriptor FindByPropertyName(String propertyName, bool obtainFragment) { var index = 0; var foundIndex = 0; var foundCount = 0; EventType streamType = null; for (var i = 0; i < _eventTypes.Length; i++) { if (_eventTypes[i] != null) { Type propertyType = null; var found = false; FragmentEventType fragmentEventTypeX = null; if (_eventTypes[i].IsProperty(propertyName)) { propertyType = _eventTypes[i].GetPropertyType(propertyName); if (obtainFragment) { fragmentEventTypeX = _eventTypes[i].GetFragmentType(propertyName); } found = true; } else { // mapped(expression) or array(expression) are not property names but expressions against a property by name "mapped" or "array" var descriptor = _eventTypes[i].GetPropertyDescriptor(propertyName); if (descriptor != null) { found = true; propertyType = descriptor.PropertyType; if (descriptor.IsFragment && obtainFragment) { fragmentEventTypeX = _eventTypes[i].GetFragmentType(propertyName); } } } if (found) { streamType = _eventTypes[i]; foundCount++; foundIndex = index; // If the property could be resolved from stream 0 then we don't need to look further if ((i == 0) && _isStreamZeroUnambigous) { return(new PropertyResolutionDescriptor(_streamNames[0], _eventTypes[0], propertyName, 0, propertyType, fragmentEventTypeX)); } } } index++; } HandleFindExceptions(propertyName, foundCount, streamType); FragmentEventType fragmentEventType = null; if (obtainFragment) { fragmentEventType = streamType.GetFragmentType(propertyName); } return(new PropertyResolutionDescriptor(_streamNames[foundIndex], _eventTypes[foundIndex], propertyName, foundIndex, streamType.GetPropertyType(propertyName), fragmentEventType)); }
/// <summary> /// Ctor. /// </summary> /// <param name="eventType">to render</param> /// <param name="stack">the stack of properties to avoid looping</param> /// <param name="options">rendering options</param> public RendererMeta(EventType eventType, Stack <EventTypePropertyPair> stack, RendererMetaOptions options) { var gettersSimple = new List <GetterPair>(); var gettersIndexed = new List <GetterPair>(); var gettersMapped = new List <GetterPair>(); var gettersNested = new List <NestedGetterPair>(); var descriptors = eventType.PropertyDescriptors; foreach (EventPropertyDescriptor desc in descriptors) { String propertyName = desc.PropertyName; if ((!desc.IsIndexed) && (!desc.IsMapped) && (!desc.IsFragment)) { var getter = eventType.GetGetter(propertyName); if (getter == null) { log.Warn("No getter returned for event type '" + eventType.Name + "' and property '" + propertyName + "'"); continue; } gettersSimple.Add(new GetterPair(getter, propertyName, OutputValueRendererFactory.GetOutputValueRenderer( desc.PropertyType, options))); } if (desc.IsIndexed && !desc.RequiresIndex && (!desc.IsFragment)) { var getter = eventType.GetGetter(propertyName); if (getter == null) { log.Warn("No getter returned for event type '" + eventType.Name + "' and property '" + propertyName + "'"); continue; } gettersIndexed.Add(new GetterPair(getter, propertyName, OutputValueRendererFactory.GetOutputValueRenderer( desc.PropertyType, options))); } if (desc.IsMapped && !desc.RequiresMapKey && (!desc.IsFragment)) { var getter = eventType.GetGetter(propertyName); if (getter == null) { log.Warn("No getter returned for event type '" + eventType.Name + "' and property '" + propertyName + "'"); continue; } gettersMapped.Add(new GetterPair(getter, propertyName, OutputValueRendererFactory.GetOutputValueRenderer( desc.PropertyType, options))); } if (desc.IsFragment) { var getter = eventType.GetGetter(propertyName); var fragmentType = eventType.GetFragmentType(propertyName); if (getter == null) { log.Warn("No getter returned for event type '" + eventType.Name + "' and property '" + propertyName + "'"); continue; } if (fragmentType == null) { log.Warn("No fragment type returned for event type '" + eventType.Name + "' and property '" + propertyName + "'"); continue; } var pair = new EventTypePropertyPair(fragmentType.FragmentType, propertyName); if ((options.PreventLooping && stack.Contains(pair))) { continue; // prevent looping behavior on self-references } stack.Push(pair); var fragmentMetaData = new RendererMeta(fragmentType.FragmentType, stack, options); stack.Pop(); gettersNested.Add(new NestedGetterPair(getter, propertyName, fragmentMetaData, fragmentType.IsIndexed)); } } gettersSimple.Sort((gp1, gp2) => gp1.Name.CompareTo(gp2.Name)); gettersIndexed.Sort((gp1, gp2) => gp1.Name.CompareTo(gp2.Name)); gettersMapped.Sort((gp1, gp2) => gp1.Name.CompareTo(gp2.Name)); gettersNested.Sort((gp1, gp2) => gp1.Name.CompareTo(gp2.Name)); simpleProperties = gettersSimple.ToArray(); indexProperties = gettersIndexed.ToArray(); mappedProperties = gettersMapped.ToArray(); nestedProperties = gettersNested.ToArray(); }
public FragmentTypeEval(int streamId, EventType eventType, string resolvedPropertyName) { _streamId = streamId; _getter = eventType.GetGetter(resolvedPropertyName); _fragmentType = eventType.GetFragmentType(resolvedPropertyName).FragmentType.Name; }
private PropertyResolutionDescriptor FindByStreamNameOnly(String propertyName, String streamName, bool explicitPropertiesOnly, bool obtainFragment) { var index = 0; EventType streamType = null; // Stream name resultion examples: // A) select A1.price from Event.price as A2 => mismatch stream name, cannot resolve // B) select Event1.price from Event2.price => mismatch event type name, cannot resolve // C) select default.Event2.price from Event2.price => possible prefix of engine name for (var i = 0; i < _eventTypes.Length; i++) { if (_eventTypes[i] == null) { index++; continue; } if ((_streamNames[i] != null) && (_streamNames[i].Equals(streamName))) { streamType = _eventTypes[i]; break; } // If the stream name is the event type name, that is also acceptable if ((_eventTypes[i].Name != null) && (_eventTypes[i].Name.Equals(streamName))) { streamType = _eventTypes[i]; break; } index++; } if (streamType == null) { var message = "Failed to find a stream named '" + streamName + "'"; var msgGen = new StreamNotFoundExceptionSuggestionGen(_eventTypes, _streamNames, streamName); throw new StreamNotFoundException(message, msgGen.GetSuggestion); } Type propertyType = null; FragmentEventType fragmentEventType = null; if (!explicitPropertiesOnly) { propertyType = streamType.GetPropertyType(propertyName); if (propertyType == null) { var desc = streamType.GetPropertyDescriptor(propertyName); if (desc == null) { throw HandlePropertyNotFound(propertyName, streamName, streamType); } propertyType = desc.PropertyType; if (obtainFragment && desc.IsFragment) { fragmentEventType = streamType.GetFragmentType(propertyName); } } else { if (obtainFragment) { fragmentEventType = streamType.GetFragmentType(propertyName); } } } else { var explicitProps = streamType.PropertyDescriptors; var found = false; foreach (var prop in explicitProps) { if (prop.PropertyName.Equals(propertyName)) { propertyType = prop.PropertyType; if (obtainFragment && prop.IsFragment) { fragmentEventType = streamType.GetFragmentType(propertyName); } found = true; break; } } if (!found) { throw HandlePropertyNotFound(propertyName, streamName, streamType); } } return(new PropertyResolutionDescriptor(streamName, streamType, propertyName, index, propertyType, fragmentEventType)); }
public static EventBeanUpdateHelper Make( string updatedWindowOrTableName, EventTypeSPI eventTypeSPI, IList <OnTriggerSetAssignment> assignments, string updatedAlias, EventType optionalTriggeringEventType, bool isCopyOnWrite) { IList <EventBeanUpdateItem> updateItems = new List <EventBeanUpdateItem>(); IList <string> properties = new List <string>(); for (var i = 0; i < assignments.Count; i++) { var assignment = assignments[i]; EventBeanUpdateItem updateItem; // determine whether this is a "property=value" assignment, we use property setters in this case var possibleAssignment = ExprNodeUtility.CheckGetAssignmentToProp(assignment.Expression); // handle assignment "property = value" if (possibleAssignment != null) { var propertyName = possibleAssignment.First; var writableProperty = eventTypeSPI.GetWritableProperty(propertyName); // check assignment to indexed or mapped property if (writableProperty == null) { var nameWriteablePair = CheckIndexedOrMappedProp(possibleAssignment.First, updatedWindowOrTableName, updatedAlias, eventTypeSPI); propertyName = nameWriteablePair.First; writableProperty = nameWriteablePair.Second; } var evaluator = possibleAssignment.Second.ExprEvaluator; var writers = eventTypeSPI.GetWriter(propertyName); var notNullableField = writableProperty.PropertyType.IsPrimitive; properties.Add(propertyName); var widener = TypeWidenerFactory.GetCheckPropertyAssignType(ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(possibleAssignment.Second), possibleAssignment.Second.ExprEvaluator.ReturnType, writableProperty.PropertyType, propertyName); // check event type assignment if (optionalTriggeringEventType != null && possibleAssignment.Second is ExprIdentNode) { var node = (ExprIdentNode)possibleAssignment.Second; var fragmentRHS = optionalTriggeringEventType.GetFragmentType(node.ResolvedPropertyName); var fragmentLHS = eventTypeSPI.GetFragmentType(possibleAssignment.First); if (fragmentRHS != null && fragmentLHS != null && !EventTypeUtility.IsTypeOrSubTypeOf(fragmentRHS.FragmentType, fragmentLHS.FragmentType)) { throw new ExprValidationException("Invalid assignment to property '" + possibleAssignment.First + "' event type '" + fragmentLHS.FragmentType.Name + "' from event type '" + fragmentRHS.FragmentType.Name + "'"); } } updateItem = new EventBeanUpdateItem(evaluator, propertyName, writers, notNullableField, widener); } // handle non-assignment, i.e. UDF or other expression else { var evaluator = assignment.Expression.ExprEvaluator; updateItem = new EventBeanUpdateItem(evaluator, null, null, false, null); } updateItems.Add(updateItem); } // copy-on-write is the default event semantics as events are immutable EventBeanCopyMethod copyMethod; if (isCopyOnWrite) { // obtain copy method IList <string> propertiesUniqueList = new List <string>(new HashSet <string>(properties)); var propertiesArray = propertiesUniqueList.ToArray(); copyMethod = eventTypeSPI.GetCopyMethod(propertiesArray); if (copyMethod == null) { throw new ExprValidationException("Event type does not support event bean copy"); } } else { // for in-place update, determine assignment expressions to use "initial" to access prior-change values // the copy-method is optional copyMethod = null; var propertiesInitialValue = DeterminePropertiesInitialValue(assignments); if (!propertiesInitialValue.IsEmpty()) { var propertiesInitialValueArray = propertiesInitialValue.ToArray(); copyMethod = eventTypeSPI.GetCopyMethod(propertiesInitialValueArray); } } var updateItemsArray = updateItems.ToArray(); return(new EventBeanUpdateHelper(copyMethod, updateItemsArray)); }
public FragmentEventType GetFragmentType(String propertyName) { var item = _propertyItems.Get(propertyName); if (item != null) // may contain null values { return(item.FragmentEventType); } // see if this is a nested property var index = ASTUtil.UnescapedIndexOfDot(propertyName); if (index == -1) { // dynamic simple property if (propertyName.EndsWith("?")) { return(null); } // parse, can be an indexed property var property = PropertyParser.ParseAndWalk(propertyName); if (property is IndexedProperty) { var indexedProp = (IndexedProperty)property; var type = NestableTypes.Get(indexedProp.PropertyNameAtomic); if (type == null) { return(null); } else if (type is EventType[]) { var eventType = ((EventType[])type)[0]; return(new FragmentEventType(eventType, false, false)); } else if (type is String) { var propTypeName = type.ToString(); var isArray = EventTypeUtility.IsPropertyArray(propTypeName); if (!isArray) { return(null); } propTypeName = EventTypeUtility.GetPropertyRemoveArray(propTypeName); EventType innerType = EventAdapterService.GetEventTypeByName(propTypeName); if (!(innerType is BaseNestableEventType)) { return(null); } return(new FragmentEventType(innerType, false, false)); // false since an index is present } if (!(type is Type)) { return(null); } if (!((Type)type).IsArray) { return(null); } // its an array return(EventBeanUtility.CreateNativeFragmentType(((Type)type).GetElementType(), null, EventAdapterService)); } else if (property is MappedProperty) { // No type information available for the inner event return(null); } else { return(null); } } // Map event types allow 2 types of properties inside: // - a property that is a object is interrogated via bean property getters and BeanEventType // - a property that is a Map itself is interrogated via map property getters // The property getters therefore act on // Take apart the nested property into a map key and a nested value class property name var propertyMap = ASTUtil.UnescapeDot(propertyName.Substring(0, index)); var propertyNested = propertyName.Substring(index + 1); // If the property is dynamic, it cannot be a fragment if (propertyMap.EndsWith("?")) { return(null); } var nestedType = NestableTypes.Get(propertyMap); if (nestedType == null) { // parse, can be an indexed property var property = PropertyParser.ParseAndWalk(propertyMap); if (property is IndexedProperty) { var indexedProp = (IndexedProperty)property; var type = NestableTypes.Get(indexedProp.PropertyNameAtomic); if (type == null) { return(null); } // handle map-in-map case if (type is String) { var propTypeName = type.ToString(); var isArray = EventTypeUtility.IsPropertyArray(propTypeName); if (isArray) { propTypeName = EventTypeUtility.GetPropertyRemoveArray(propTypeName); } EventType innerType = EventAdapterService.GetEventTypeByName(propTypeName); if (!(innerType is BaseNestableEventType)) { return(null); } return(innerType.GetFragmentType(propertyNested)); } // handle eventtype[] in map else if (type is EventType[]) { var innerType = ((EventType[])type)[0]; return(innerType.GetFragmentType(propertyNested)); } // handle array class in map case else { if (!(type is Type)) { return(null); } if (!((Type)type).IsArray) { return(null); } var fragmentParent = EventBeanUtility.CreateNativeFragmentType( (Type)type, null, EventAdapterService); if (fragmentParent == null) { return(null); } return(fragmentParent.FragmentType.GetFragmentType(propertyNested)); } } else if (property is MappedProperty) { // No type information available for the property's map value return(null); } else { return(null); } } // If there is a map value in the map, return the Object value if this is a dynamic property if (ReferenceEquals(nestedType, typeof(IDictionary <string, object>))) { return(null); } else if (nestedType is IDictionary <string, object> ) { return(null); } else if (nestedType is Type) { var simpleClass = (Type)nestedType; if (!TypeHelper.IsFragmentableType(simpleClass)) { return(null); } EventType nestedEventType = EventAdapterService.BeanEventTypeFactory.CreateBeanTypeDefaultName(simpleClass); return(nestedEventType.GetFragmentType(propertyNested)); } else if (nestedType is EventType) { var innerType = (EventType)nestedType; return(innerType.GetFragmentType(propertyNested)); } else if (nestedType is EventType[]) { var innerType = (EventType[])nestedType; return(innerType[0].GetFragmentType(propertyNested)); } else if (nestedType is String) { var nestedName = nestedType.ToString(); var isArray = EventTypeUtility.IsPropertyArray(nestedName); if (isArray) { nestedName = EventTypeUtility.GetPropertyRemoveArray(nestedName); } var innerType = EventAdapterService.GetEventTypeByName(nestedName); if (!(innerType is BaseNestableEventType)) { return(null); } return(innerType.GetFragmentType(propertyNested)); } else { var message = "Nestable map type configuration encountered an unexpected value type of '" + nestedType.GetType() + " for property '" + propertyName + "', expected Class, typeof(Map) or IDictionary<String, Object> as value type"; throw new PropertyAccessException(message); } }
public static EventBeanUpdateHelperForge Make( string updatedWindowOrTableName, EventTypeSPI eventTypeSPI, IList <OnTriggerSetAssignment> assignments, string updatedAlias, EventType optionalTriggeringEventType, bool isCopyOnWrite, string statementName, EventTypeAvroHandler avroHandler) { IList <EventBeanUpdateItemForge> updateItems = new List <EventBeanUpdateItemForge>(); IList <string> properties = new List <string>(); TypeWidenerCustomizer typeWidenerCustomizer = avroHandler.GetTypeWidenerCustomizer(eventTypeSPI); for (int i = 0; i < assignments.Count; i++) { OnTriggerSetAssignment desc = assignments[i]; ExprAssignment assignment = desc.Validated; if (assignment == null) { throw new IllegalStateException("Assignment has not been validated"); } try { EventBeanUpdateItemForge updateItem; if (assignment is ExprAssignmentStraight) { ExprAssignmentStraight straight = (ExprAssignmentStraight)assignment; // handle assignment "property = value" if (straight.Lhs is ExprAssignmentLHSIdent) { ExprAssignmentLHSIdent ident = (ExprAssignmentLHSIdent)straight.Lhs; string propertyName = ident.Ident; EventPropertyDescriptor writableProperty = eventTypeSPI.GetWritableProperty(propertyName); // check assignment to indexed or mapped property if (writableProperty == null) { Pair <string, EventPropertyDescriptor> nameWriteablePair = CheckIndexedOrMappedProp( propertyName, updatedWindowOrTableName, updatedAlias, eventTypeSPI); propertyName = nameWriteablePair.First; writableProperty = nameWriteablePair.Second; } ExprNode rhsExpr = straight.Rhs; ExprForge rhsForge = rhsExpr.Forge; EventPropertyWriterSPI writer = eventTypeSPI.GetWriter(propertyName); bool notNullableField = writableProperty.PropertyType.IsPrimitive; properties.Add(propertyName); TypeWidenerSPI widener; try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(rhsExpr), rhsForge.EvaluationType, writableProperty.PropertyType, propertyName, false, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } // check event type assignment bool useUntypedAssignment = false; bool useTriggeringEvent = false; if (optionalTriggeringEventType != null) { // handle RHS is ident node if (rhsExpr is ExprIdentNode) { ExprIdentNode node = (ExprIdentNode)rhsExpr; FragmentEventType fragmentRHS = optionalTriggeringEventType.GetFragmentType(node.ResolvedPropertyName); FragmentEventType fragmentLHS = eventTypeSPI.GetFragmentType(propertyName); if (fragmentRHS != null && fragmentLHS != null) { if (!EventTypeUtility.IsTypeOrSubTypeOf(fragmentRHS.FragmentType, fragmentLHS.FragmentType)) { throw MakeEventTypeMismatch(propertyName, fragmentLHS.FragmentType, fragmentRHS.FragmentType); } } // we don't need to cast if it is a self-assignment and LHS is an event and target needs no writer if (node.StreamId == 0 && fragmentLHS != null && eventTypeSPI is BaseNestableEventType) { useUntypedAssignment = true; } } // handle RHS is a stream of the triggering event itself if (rhsExpr is ExprStreamUnderlyingNode) { ExprStreamUnderlyingNode und = (ExprStreamUnderlyingNode)rhsExpr; if (und.StreamId == 1) { FragmentEventType fragmentLHS = eventTypeSPI.GetFragmentType(propertyName); if (fragmentLHS != null && optionalTriggeringEventType is BaseNestableEventType && !EventTypeUtility.IsTypeOrSubTypeOf(optionalTriggeringEventType, fragmentLHS.FragmentType)) { throw MakeEventTypeMismatch(propertyName, fragmentLHS.FragmentType, optionalTriggeringEventType); } // we use the event itself for assignment and target needs no writer if (eventTypeSPI is BaseNestableEventType) { useUntypedAssignment = true; useTriggeringEvent = true; } } } } updateItem = new EventBeanUpdateItemForge( rhsForge, propertyName, writer, notNullableField, widener, useUntypedAssignment, useTriggeringEvent, null); } else if (straight.Lhs is ExprAssignmentLHSArrayElement) { // handle "property[expr] = value" ExprAssignmentLHSArrayElement arrayElementLHS = (ExprAssignmentLHSArrayElement)straight.Lhs; string arrayPropertyName = arrayElementLHS.Ident; ExprNode rhs = straight.Rhs; Type evaluationType = rhs.Forge.EvaluationType; Type propertyType = eventTypeSPI.GetPropertyType(arrayPropertyName); if (!eventTypeSPI.IsProperty(arrayPropertyName)) { throw new ExprValidationException("Property '" + arrayPropertyName + "' could not be found"); } if (propertyType == null || !propertyType.IsArray) { throw new ExprValidationException("Property '" + arrayPropertyName + "' is not an array"); } EventPropertyGetterSPI getter = eventTypeSPI.GetGetterSPI(arrayPropertyName); Type componentType = propertyType.GetElementType(); if (!TypeHelper.IsAssignmentCompatible(evaluationType, componentType)) { throw new ExprValidationException( "Invalid assignment to property '" + arrayPropertyName + "' component type '" + componentType.CleanName() + "' from expression returning '" + evaluationType.CleanName() + "'"); } TypeWidenerSPI widener; try { widener = TypeWidenerFactory.GetCheckPropertyAssignType( ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(straight.Rhs), evaluationType, componentType, arrayPropertyName, false, typeWidenerCustomizer, statementName); } catch (TypeWidenerException ex) { throw new ExprValidationException(ex.Message, ex); } EventBeanUpdateItemArray arrayInfo = new EventBeanUpdateItemArray( arrayPropertyName, arrayElementLHS.IndexExpression, propertyType, getter); updateItem = new EventBeanUpdateItemForge( rhs.Forge, arrayPropertyName, null, false, widener, false, false, arrayInfo); } else { throw new IllegalStateException("Unrecognized LHS assignment " + straight); } } else if (assignment is ExprAssignmentCurly) { // handle non-assignment, i.e. UDF or other expression ExprAssignmentCurly dot = (ExprAssignmentCurly)assignment; updateItem = new EventBeanUpdateItemForge( dot.Expression.Forge, null, null, false, null, false, false, null); } else { throw new IllegalStateException("Unrecognized assignment " + assignment); } updateItems.Add(updateItem); } catch (ExprValidationException ex) { throw new ExprValidationException( "Failed to validate assignment expression '" + ExprNodeUtilityPrint.ToExpressionStringMinPrecedenceSafe(assignment.OriginalExpression) + "': " + ex.Message, ex); } } // copy-on-write is the default event semantics as events are immutable EventBeanCopyMethodForge copyMethod; if (isCopyOnWrite) { // obtain copy method List <string> propertiesUniqueList = new List <string>(new HashSet <string>(properties)); string[] propertiesArray = propertiesUniqueList.ToArray(); copyMethod = eventTypeSPI.GetCopyMethodForge(propertiesArray); if (copyMethod == null) { throw new ExprValidationException("Event type does not support event bean copy"); } } else { // for in-place update, determine assignment expressions to use "initial" to access prior-change values // the copy-method is optional copyMethod = null; ISet <string> propertiesInitialValue = DeterminePropertiesInitialValue(assignments); if (!propertiesInitialValue.IsEmpty()) { string[] propertiesInitialValueArray = propertiesInitialValue.ToArray(); copyMethod = eventTypeSPI.GetCopyMethodForge(propertiesInitialValueArray); } } EventBeanUpdateItemForge[] updateItemsArray = updateItems.ToArray(); return(new EventBeanUpdateHelperForge(eventTypeSPI, copyMethod, updateItemsArray)); }
public FragmentEventType GetFragmentType(string propertyName) { var item = _propertyItems.Get(propertyName); if (item != null) { // may contain null values return item.FragmentEventType; } // see if this is a nested property var index = StringValue.UnescapedIndexOfDot(propertyName); if (index == -1) { // dynamic simple property if (propertyName.EndsWith("?")) { return null; } // parse, can be an indexed property var property = PropertyParser.ParseAndWalkLaxToSimple(propertyName); if (property is IndexedProperty indexedProp) { var type = _nestableTypes.Get(indexedProp.PropertyNameAtomic); if (type == null) { return null; } if (type is EventType[] eventTypesArray) { var eventType = eventTypesArray[0]; return new FragmentEventType(eventType, false, false); } if (type is TypeBeanOrUnderlying[] beanOrUnderlyings) { var innerType = beanOrUnderlyings[0].EventType; if (!(innerType is BaseNestableEventType)) { return null; } return new FragmentEventType(innerType, false, false); // false since an index is present } if (!(type is Type)) { return null; } if (!((Type) type).IsArray) { return null; } // its an array return EventBeanUtility.CreateNativeFragmentType( ((Type) type).GetElementType(), null, _beanEventTypeFactory, _publicFields); } if (property is MappedProperty) { // No type information available for the inner event return null; } return null; } // Map event types allow 2 types of properties inside: // - a property that is a object is interrogated via bean property getters and BeanEventType // - a property that is a Map itself is interrogated via map property getters // The property getters therefore act on // Take apart the nested property into a map key and a nested value class property name var propertyMap = StringValue.UnescapeDot(propertyName.Substring(0, index)); var propertyNested = propertyName.Substring(index + 1); // If the property is dynamic, it cannot be a fragment if (propertyMap.EndsWith("?")) { return null; } var nestedType = _nestableTypes.Get(propertyMap); if (nestedType == null) { // parse, can be an indexed property var property = PropertyParser.ParseAndWalkLaxToSimple(propertyMap); if (property is IndexedProperty indexedProp) { var type = _nestableTypes.Get(indexedProp.PropertyNameAtomic); if (type == null) { return null; } // handle map-in-map case if (type is TypeBeanOrUnderlying[] beanOrUnderlyings) { var innerType = beanOrUnderlyings[0].EventType; if (!(innerType is BaseNestableEventType)) { return null; } return innerType.GetFragmentType(propertyNested); } if (type is EventType[] innerEventTypeArray) { // handle EventType[] in map var innerType = innerEventTypeArray[0]; return innerType.GetFragmentType(propertyNested); } // handle array class in map case if (!(type is Type)) { return null; } if (!((Type) type).IsArray) { return null; } var fragmentParent = EventBeanUtility.CreateNativeFragmentType( (Type) type, null, _beanEventTypeFactory, _publicFields); return fragmentParent?.FragmentType.GetFragmentType(propertyNested); } if (property is MappedProperty) { // No type information available for the property's map value return null; } return null; } // If there is a map value in the map, return the Object value if this is a dynamic property if (ReferenceEquals(nestedType, typeof(IDictionary<string, object>))) { return null; } if (nestedType is IDictionary<string, object>) { return null; } if (nestedType is Type simpleClass) { if (!simpleClass.IsFragmentableType()) { return null; } EventType nestedEventType = _beanEventTypeFactory.GetCreateBeanType(simpleClass, _publicFields); return nestedEventType.GetFragmentType(propertyNested); } if (nestedType is EventType innerEventType) { return innerEventType.GetFragmentType(propertyNested); } if (nestedType is EventType[] eventTypeArray) { return eventTypeArray[0].GetFragmentType(propertyNested); } if (nestedType is TypeBeanOrUnderlying typeBeanOrUnderlying) { var innerType = typeBeanOrUnderlying.EventType; if (!(innerType is BaseNestableEventType)) { return null; } return innerType.GetFragmentType(propertyNested); } if (nestedType is TypeBeanOrUnderlying[] typeBeanOrUnderlyings) { var innerType = typeBeanOrUnderlyings[0].EventType; if (!(innerType is BaseNestableEventType)) { return null; } return innerType.GetFragmentType(propertyNested); } var message = "Nestable map type configuration encountered an unexpected value type of '" + nestedType.GetType() + " for property '" + propertyName + "', expected Class, Map.class or Map<String, Object> as value type"; throw new PropertyAccessException(message); }