Skip to content

Commit

Permalink
DefaultIfEmpty
Browse files Browse the repository at this point in the history
  • Loading branch information
dibiancoj committed Jun 10, 2016
1 parent 1a295de commit 618d762
Show file tree
Hide file tree
Showing 19 changed files with 410 additions and 87 deletions.
17 changes: 17 additions & 0 deletions Linq4Javascript/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ public ActionResult Index()

//var groupby = Team.BuildTeamsLazy().GroupBy(x => x.SportId).ToArray();

//var z = new List<int> { };

//var zz = z.DefaultIfEmpty();

//var lst = new List<Team>();

//if (true == true)
//{
// lst.Add(new Team { TeamId = 100, SportId = 100 });
// lst.Add(new Team { TeamId = 200, SportId = 200 });
//}

//foreach (var t in lst.DefaultIfEmpty(new Team { SportId = 0, TeamDescription = "N/A", TeamId = 0 }))
//{
// string s = t.SportId.ToString();
//}

return View();
}

Expand Down
10 changes: 6 additions & 4 deletions Linq4Javascript/Linq4Javascript.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Linq4Javascript</RootNamespace>
<AssemblyName>Linq4Javascript</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<MvcBuildViews>false</MvcBuildViews>
<UseIISExpress>true</UseIISExpress>
<IISExpressSSLPort />
Expand All @@ -26,6 +26,7 @@
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<UseGlobalApplicationHostFile />
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
Expand All @@ -48,14 +49,14 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data.Entity" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web.DynamicData" />
<Reference Include="System.Web.Entity" />
<Reference Include="System.Web.ApplicationServices" />
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Core" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Abstractions" />
<Reference Include="System.Web.Routing" />
Expand Down Expand Up @@ -109,6 +110,7 @@
<Private>True</Private>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.1.2\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="WebGrease">
<Private>True</Private>
<HintPath>..\packages\WebGrease.1.5.2\lib\WebGrease.dll</HintPath>
Expand Down
1 change: 1 addition & 0 deletions Linq4Javascript/Scripts/JLinq Change Log.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,5 @@

3.0.4 - 6/10/2016
-Added GroupJoin
-Added DefaultIfEmpty
-Updated to qunit 1.23.1
84 changes: 69 additions & 15 deletions Linq4Javascript/Scripts/JLinq.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Linq4Javascript/Scripts/JLinq.js.map

Large diffs are not rendered by default.

121 changes: 104 additions & 17 deletions Linq4Javascript/Scripts/JLinq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ module ToracTechnologies {
//#endregion

//join 2 recordsets where the property selector matches on both collections
public Join<T, TOuterArrayType, TSelectorDataType, TJoinResult>(OuterJoinArray: TOuterArrayType[] | Iterator<TOuterArrayType>, InnerKeySelector: (InnerRecord: T) => TSelectorDataType, OuterKeySelector: (OuterRecord: TOuterArrayType) => TSelectorDataType, JoinSelector: (InnerRecord: T, OuterRecord: TOuterArrayType) => TJoinResult): JoinIterator<T, TOuterArrayType, TSelectorDataType, TJoinResult> {
public Join<TOuterArrayType, TSelectorDataType, TJoinResult>(OuterJoinArray: TOuterArrayType[] | Iterator<TOuterArrayType>, InnerKeySelector: (InnerRecord: T) => TSelectorDataType, OuterKeySelector: (OuterRecord: TOuterArrayType) => TSelectorDataType, JoinSelector: (InnerRecord: T, OuterRecord: TOuterArrayType) => TJoinResult): JoinIterator<T, TOuterArrayType, TSelectorDataType, TJoinResult> {

//iterator to convert into
var ConvertToIterator: Iterator<TOuterArrayType>;
Expand All @@ -490,7 +490,7 @@ module ToracTechnologies {
}

//join 2 recordsets where the property selector matches on both collections. The outer table returns the collection in the result selector
public GroupJoin<T, TOuterArrayType, TSelectorDataType, TJoinResult>(OuterJoinArray: TOuterArrayType[] | Iterator<TOuterArrayType>, InnerKeySelector: (InnerRecord: T) => TSelectorDataType, OuterKeySelector: (OuterRecord: TOuterArrayType) => TSelectorDataType, JoinSelector: (InnerRecord: T, OuterRecord: TOuterArrayType[]) => TJoinResult): GroupJoinIterator<T, TOuterArrayType, TSelectorDataType, TJoinResult> {
public GroupJoin<TOuterArrayType, TSelectorDataType, TJoinResult>(OuterJoinArray: TOuterArrayType[] | Iterator<TOuterArrayType>, InnerKeySelector: (InnerRecord: T) => TSelectorDataType, OuterKeySelector: (OuterRecord: TOuterArrayType) => TSelectorDataType, JoinSelector: (InnerRecord: T, OuterRecord: TOuterArrayType[]) => TJoinResult): GroupJoinIterator<T, TOuterArrayType, TSelectorDataType, TJoinResult> {

//iterator to convert into
var ConvertToIterator: Iterator<TOuterArrayType>;
Expand All @@ -506,6 +506,11 @@ module ToracTechnologies {
return new GroupJoinIterator<T, TOuterArrayType, TSelectorDataType, TJoinResult>(<any>this, ConvertToIterator, InnerKeySelector, OuterKeySelector, JoinSelector);
}

//returns the default value of T if no items exists. If T is a class it will return null. If T is a number it will return 0. bool will return false, etc.
public DefaultIfEmpty(DefaultValue: T): DefaultIfEmptyIterator<T> {
return new DefaultIfEmptyIterator<T>(this, DefaultValue);
}

//#endregion

//#region Public Non Linq Iterator Functionality Methods
Expand Down Expand Up @@ -1191,6 +1196,96 @@ module ToracTechnologies {

//#region Linq Functionality Classes

//Class is used to implement the Where Method Iterator
export class DefaultIfEmptyIterator<T> extends Iterator<T>
implements IChainable<T, T> {

//#region Constructor

constructor(PreviousLambdaExpression: IChainable<T, T>, DefaultElementIfEmpty: T) {

//because we inherit from Iterator we need to call the base class
super();

//set the queryable source
this.PreviousExpression = PreviousLambdaExpression;

//set the default element if the collection before is empty
this.DefaultElementWhenEmpty = DefaultElementIfEmpty;

//throw this into a variable so we can debug this thing when we go from CollectionSource To CollectionSource and check the type
this.TypeOfObject = "DefaultIfEmptyIterator";
}

//#endregion

//#region Properties

private DefaultElementWhenEmpty: T;
private HasFirstItem: boolean = null;

//#endregion

//#region Methods

public ResetIterator() {
this.HasFirstItem = null;
}

public Next(): IteratorResult<T> {

//holds the next available item
var NextItem: IteratorResult<T>;

//just keep looping as we recurse through the CollectionSource which contains all the calls down the tree
while (true) {

//if we have already set it to false we are done
if (this.HasFirstItem != null && !this.HasFirstItem) {
return new IteratorResult<T>(null, IteratorStatus.Completed);
}

//grab the next level and then the next guy for that level
NextItem = this.PreviousExpression.Next();

//if its null or we want to grab this guy because he meets the criteria then jump out of the loop
//if it doesnt match the filter then we just keep going in the loop
if (NextItem.CurrentStatus === IteratorStatus.Completed && !this.HasFirstItem) {

//flip the flag to false so when we come back we know we are done
this.HasFirstItem = false;

//otherwise return what they passed in
return new IteratorResult<T>(this.DefaultElementWhenEmpty, IteratorStatus.Running);
}
else if (NextItem.CurrentStatus === IteratorStatus.Completed) {

//we found this guy so return it...after we return this method we will jump a level to the next level down the tree
return NextItem;
}
else if (this.HasFirstItem == null) {

//set that we have an item
this.HasFirstItem = true;

//return the item now
return NextItem;
}
else {
//has items...so just return it
return NextItem;
}
}
}

public AsyncSerializedFunc(): Array<KeyValuePair<string, string>> {
throw 'DefaultIfEmpty Method Not Supported In Async Mode';
}

//#endregion

}

//Class is used to implement the join method iterator. Used to essentially build a database join type iterator
export class JoinIterator<T, TOuterArrayType, TSelectorDataType, TJoinResult> extends Iterator<TJoinResult>
implements IChainable<T, TJoinResult> {
Expand Down Expand Up @@ -1286,13 +1381,6 @@ module ToracTechnologies {

public AsyncSerializedFunc(): Array<KeyValuePair<string, string>> {
throw 'Join Method Not Supported In Async Mode';
//return [
// new KeyValuePair('OuterJoinArray', JSON.stringify(this.OuterJoinArray)),
// new KeyValuePair('InnerKeyFuncSelector', super.SerializeMethod(this.InnerKeyFuncSelector)),
// new KeyValuePair('OuterKeyFuncSelector', super.SerializeMethod(this.OuterKeyFuncSelector)),
// new KeyValuePair('JoinFuncSelector', super.SerializeMethod(this.JoinFuncSelector))
// //new KeyValuePair('Matches', super.SerializeMethod(this.Matches))
//];
}

//#endregion
Expand Down Expand Up @@ -1386,14 +1474,7 @@ module ToracTechnologies {
}

public AsyncSerializedFunc(): Array<KeyValuePair<string, string>> {
throw 'Join Method Not Supported In Async Mode';
//return [
// new KeyValuePair('OuterJoinArray', JSON.stringify(this.OuterJoinArray)),
// new KeyValuePair('InnerKeyFuncSelector', super.SerializeMethod(this.InnerKeyFuncSelector)),
// new KeyValuePair('OuterKeyFuncSelector', super.SerializeMethod(this.OuterKeyFuncSelector)),
// new KeyValuePair('JoinFuncSelector', super.SerializeMethod(this.JoinFuncSelector))
// //new KeyValuePair('Matches', super.SerializeMethod(this.Matches))
//];
throw 'GroupJoin Method Not Supported In Async Mode';
}

//#endregion
Expand Down Expand Up @@ -4105,6 +4186,8 @@ interface Array<T> {

Join<T, TOuterArrayType, TSelectorDataType, TResultDataType>(OuterJoinArray: TOuterArrayType[] | ToracTechnologies.JLinq.Iterator<TOuterArrayType>, InnerKeySelector: (InnerRecord: T) => TSelectorDataType, OuterKeySelector: (OuterRecord: TOuterArrayType) => TSelectorDataType, JoinSelector: (InnerRecord: T, OuterRecord: TOuterArrayType) => TResultDataType): ToracTechnologies.JLinq.JoinIterator<T, TOuterArrayType, TSelectorDataType, TResultDataType>;
GroupJoin<T, TOuterArrayType, TSelectorDataType, TResultDataType>(OuterJoinArray: TOuterArrayType[] | ToracTechnologies.JLinq.Iterator<TOuterArrayType>, InnerKeySelector: (InnerRecord: T) => TSelectorDataType, OuterKeySelector: (OuterRecord: TOuterArrayType) => TSelectorDataType, JoinSelector: (InnerRecord: T, OuterRecord: TOuterArrayType[]) => TResultDataType): ToracTechnologies.JLinq.GroupJoinIterator<T, TOuterArrayType, TSelectorDataType, TResultDataType>;

DefaultIfEmpty<T>(DefaultValue: T): ToracTechnologies.JLinq.DefaultIfEmptyIterator<T>;
}

//#endregion
Expand Down Expand Up @@ -4271,6 +4354,10 @@ Array.prototype.GroupJoin = function <TInnerArrayType, TOuterArrayType, TSelecto
return new ToracTechnologies.JLinq.Queryable<TInnerArrayType>(this).GroupJoin(OuterJoinArray, InnerKeySelector, OuterKeySelector, JoinSelector);
}

Array.prototype.DefaultIfEmpty = function <T>(DefaultValue: T): ToracTechnologies.JLinq.DefaultIfEmptyIterator<T> {
return new ToracTechnologies.JLinq.Queryable<T>(this).DefaultIfEmpty(DefaultValue);
}

//#endregion

//#endregion
Loading

0 comments on commit 618d762

Please sign in to comment.