Skip to content

Instantly share code, notes, and snippets.

@iwannabebot
Last active February 8, 2019 13:56
Show Gist options
  • Save iwannabebot/67bbe0ec8502c4a5631427e0899f9be4 to your computer and use it in GitHub Desktop.
Save iwannabebot/67bbe0ec8502c4a5631427e0899f9be4 to your computer and use it in GitHub Desktop.
XRM Metadata SDK in TypeScript
export interface XrmMetaAttribute {
LogicalName: string;
MetadataId: string;
DisplayName: DisplayName;
Description: Description;
IsCustomizable: IsCustomizable;
IsAuditEnabled: IsAuditEnabled;
OptionsSet: any;
AttributeType: string;
HasChanged?: any;
AttributeOf?: any;
ColumnNumber: number;
DeprecatedVersion?: any;
IntroducedVersion: string;
EntityLogicalName: string;
IsCustomAttribute: boolean;
IsPrimaryId: boolean;
IsPrimaryName: boolean;
IsValidForCreate: boolean;
IsValidForRead: boolean;
IsValidForUpdate: boolean;
CanBeSecuredForRead: boolean;
CanBeSecuredForCreate: boolean;
CanBeSecuredForUpdate: boolean;
IsSecured: boolean;
IsRetrievable: boolean;
IsFilterable: boolean;
IsSearchable: boolean;
IsManaged: boolean;
LinkedAttributeId?: any;
IsValidForForm: boolean;
IsRequiredForForm: boolean;
IsValidForGrid: boolean;
SchemaName: string;
ExternalName?: any;
IsLogical: boolean;
IsDataSourceSecret: boolean;
InheritsFrom?: any;
SourceType: number;
AutoNumberFormat: string;
Format: string;
ImeMode: string;
MaxLength: number;
YomiOf?: any;
IsLocalizable: boolean;
DatabaseLength: number;
FormulaDefinition?: any;
SourceTypeMask: number;
AttributeTypeName: AttributeTypeName;
IsValidForAdvancedFind: IsValidForAdvancedFind;
RequiredLevel: RequiredLevel;
FormatName: FormatName;
Targets: string[];
}
export interface XrmMetaEntity {
LogicalName: string;
MetadataId: string;
DisplayName: DisplayName;
Description: Description;
IsCustomizable: IsCustomizable;
IsAuditEnabled: IsAuditEnabled;
HasChanged: any;
ActivityTypeMask: number;
Attributes: XrmMetaAttribute[];
DisplayCollectionName: DisplayCollectionName;
IsActivity: boolean;
IsActivityParty: boolean;
IsBusinessProcessEnabled: string;
IsChildEntity: boolean;
IsCustomEntity: boolean;
IsValidForAdvancedFind: boolean;
IsValidForQueue: IsValidForQueue;
ManyToManyRelationships: XrmMetaManyToManyRelation[];
ManyToOneRelationships: XrmMetaOneToManyRelation[];
ObjectTypeCode: number;
OneToManyRelationships: XrmMetaOneToManyRelation[];
OwnershipType: string;
PrimaryIdAttribute: string;
PrimaryNameAttribute: string;
SchemaName: string;
CollectionSchemaName: string;
Keys: any;
EntitySetName: string;
_type: string;
}
export enum XrmEntityFilter {
Default = 1,
Entity = 1,
Attributes = 2,
Privileges = 4,
Relationships = 8,
All = 15
}
export interface AttributeTypeName {
Value: string;
}
export interface FormatName {
Value: string;
}
export interface RequiredLevel {
Value: string;
CanBeChanged: boolean;
ManagedPropertyLogicalName: string;
}
export interface IsValidForAdvancedFind {
Value: boolean;
CanBeChanged: boolean;
ManagedPropertyLogicalName: string;
}
export interface LocalizedLabel {
MetadataId: string;
HasChanged?: any;
IsManaged: boolean;
Label: any;
LanguageCode: number;
_type: string;
}
export interface UserLocalizedLabel {
MetadataId: string;
HasChanged?: any;
IsManaged: boolean;
Label?: any;
LanguageCode: number;
}
export interface Description {
LocalizedLabels: LocalizedLabel[];
UserLocalizedLabel: UserLocalizedLabel;
}
export interface LocalizedLabel {
Label: any;
MetadataId: string;
HasChanged?: any;
IsManaged: boolean;
LanguageCode: number;
_type: string;
}
export interface DisplayCollectionName {
LocalizedLabels: LocalizedLabel[];
UserLocalizedLabel: UserLocalizedLabel;
}
export interface LocalizedLabel {
MetadataId: string;
HasChanged?: any;
IsManaged: boolean;
Label: any;
LanguageCode: number;
_type: string;
}
export interface DisplayName {
LocalizedLabels: LocalizedLabel[];
UserLocalizedLabel: UserLocalizedLabel;
}
export interface IsAuditEnabled {
CanBeChanged: boolean;
ManagedPropertyLogicalName: string;
Value: boolean;
}
export interface IsCustomizable {
CanBeChanged: boolean;
ManagedPropertyLogicalName: string;
Value: boolean;
}
export interface IsValidForQueue {
CanBeChanged: boolean;
ManagedPropertyLogicalName: string;
Value: boolean;
}
export interface XrmMetaRelation {
IsCustomRelationship?: boolean;
IsValidForAdvancedFind?: boolean;
SchemaName: string;
RelationshipType?: XrmMetaRelationshipType;
}
export interface XrmMetaOneToManyRelation extends XrmMetaRelation {
ReferencedAttribute: string;
ReferencedEntity: string;
ReferencingAttribute: string;
ReferencingEntity: string;
ReferencedEntityNavigationPropertyName: string;
ReferencingEntityNavigationPropertyName: string;
}
export interface XrmMetaManyToManyRelation extends XrmMetaRelation {
Entity1LogicalName: string;
Entity2LogicalName: string;
IntersectEntityName: string;
Entity1IntersectAttribute: string;
Entity2IntersectAttribute: string;
Entity1NavigationPropertyName: string;
Entity2NavigationPropertyName: string;
}
export enum XrmMetaRelationshipType {
OneToManyRelationship = 0,
Default = 0,
ManyToManyRelationship = 1
}
import { Observable } from "rxjs";
import { HttpClient, HttpHeaders } from "@angular/common/http";
// tslint:disable:no-bitwise
// tslint:disable:max-line-length
export class XrmMetaSdk {
private _arrayElements = [
"Attributes",
"ManyToManyRelationships",
"ManyToOneRelationships",
"OneToManyRelationships",
"Privileges",
"LocalizedLabels",
"Options",
"Targets"
];
constructor(private http: HttpClient, private clientUrl: string) {}
public GetTables(): Observable<IQueryTable[]> {
const _this = this;
return new Observable<IQueryTable[]>(subscriber => {
if (_this.IsLocal()) {
this.http
.get<XrmMetaEntity[]>("http://localhost:54566/GetEntity")
.subscribe(
entities => {
subscriber.next(this.ParseTables(entities));
},
err => {
subscriber.error(err);
},
() => {
subscriber.complete();
}
);
} else {
_this.RetrieveAllEntities(
(entities: XrmMetaEntity[]) => {
subscriber.next(this.ParseTables(entities));
subscriber.complete();
},
err => {
subscriber.error(err);
}
);
}
});
}
public GetColumnsOfTable(table: IQueryTable): Observable<IQueryColumn[]> {
const _this = this;
return new Observable<IQueryColumn[]>(subscriber => {
if (_this.IsLocal()) {
this.http
.get<XrmMetaAttribute[]>(
"http://localhost:54566/GetAttribute/" + table.Id
)
.subscribe(
attributes => {
const columns = _this.ParseColumns(table.Id, attributes);
subscriber.next(columns);
},
err => {
subscriber.error(err);
},
() => {
subscriber.complete();
}
);
} else {
const __this = _this;
_this.RetrieveAttributes(
table.Id,
(attributes: XrmMetaAttribute[]) => {
const columns = _this.ParseColumns(table.Id, attributes);
subscriber.next(columns);
subscriber.complete();
},
err => {
subscriber.error(err);
}
);
}
});
}
public GetRelationsOfTable(table: IQueryTable): Observable<IQueryRelation[]> {
const _this = this;
return new Observable<IQueryRelation[]>(subscriber => {
if (_this.IsLocal()) {
_this.http
.get<XrmMetaEntity>(
"http://localhost:54566/GetRelationships/" + table.Id
)
.subscribe(
entity => {
const o2ms = entity.OneToManyRelationships;
const m2os = entity.ManyToOneRelationships;
const m2ms = entity.ManyToManyRelationships;
subscriber.next(this.ParseRelations(table.Id, o2ms, m2os, m2ms));
},
err => {
subscriber.error(err);
},
() => {
subscriber.complete();
}
);
} else {
const __this = _this;
__this.RetrieveRelations(
table.Id,
entity => {
const o2ms = entity.OneToManyRelationships;
const m2os = entity.ManyToOneRelationships;
const m2ms = entity.ManyToManyRelationships;
subscriber.next(this.ParseRelations(table.Id, o2ms, m2os, m2ms));
subscriber.complete();
},
err => {
subscriber.error(err);
}
);
}
});
}
private ParseTables(entities: XrmMetaEntity[]): IQueryTable[] {
const tables = entities.map(entity => {
return {
Alias: "",
Id: entity.LogicalName,
Name: this.readLabel(entity),
PrimaryKeyName: entity.PrimaryIdAttribute,
PrimaryName: entity.PrimaryNameAttribute
} as IQueryTable;
});
return tables;
}
private ParseColumns(
tableId: string,
attributes: XrmMetaAttribute[]
): IQueryColumn[] {
const columns = attributes.map(att => {
return {
Alias: "",
Id: att.LogicalName,
Name: this.readLabel(att),
Table: tableId,
OptionSet: this.readOption(att),
Type: this.readAttributeType(att.AttributeType),
Targets: att.Targets
} as IQueryColumn;
});
return columns;
}
private ParseRelations(
tableId: string,
o2ms: XrmMetaOneToManyRelation[],
m2os: XrmMetaOneToManyRelation[],
m2ms: XrmMetaManyToManyRelation[]
): IQueryRelation[] {
const relations: IQueryRelation[] = [];
for (let i = 0; i < o2ms.length; i++) {
const o2m = o2ms[i];
const relation: IQueryRelation = ({
ParentColumn: o2m.ReferencedAttribute,
ParentTable: o2m.ReferencedEntity,
ChildColumn: o2m.ReferencingAttribute,
ChildTable: o2m.ReferencingEntity,
Id: o2m.SchemaName,
RelationType: QueryRelationType.OneToMany
} as any) as IQueryRelation;
relations.push(relation);
}
for (let i = 0; i < m2os.length; i++) {
const m2o = m2os[i];
const relation: IQueryRelation = ({
ChildColumn: m2o.ReferencedAttribute,
ChildTable: m2o.ReferencedEntity,
ParentColumn: m2o.ReferencingAttribute,
ParentTable: m2o.ReferencingEntity,
Id: m2o.SchemaName,
RelationType: QueryRelationType.ManyToOne
} as any) as IQueryRelation;
relations.push(relation);
}
for (let i = 0; i < m2ms.length; i++) {
const m2m = m2ms[i];
let pC, cC, pT, cT, iP, iC;
if (m2m.Entity1LogicalName.toLowerCase() === tableId.toLowerCase()) {
pT = m2m.Entity1LogicalName;
cT = m2m.Entity2LogicalName;
iP = m2m.Entity1IntersectAttribute;
iC = m2m.Entity2IntersectAttribute;
} else {
pT = m2m.Entity2LogicalName;
cT = m2m.Entity1LogicalName;
iP = m2m.Entity2IntersectAttribute;
iC = m2m.Entity1IntersectAttribute;
}
// TODO: Add proper table id here
pC = pT + "id";
cC = cT + "id";
const relation: IQueryRelation = {
ChildColumn: cC,
ChildTable: cT,
ParentColumn: pC,
ParentTable: pT,
Id: m2m.SchemaName,
RelationType: QueryRelationType.ManyToMany,
IntermediateChildColumn: iC,
IntermediateParentColumn: iP,
IntermediateTable: m2m.IntersectEntityName
} as IQueryRelation;
relations.push(relation);
}
return relations;
}
public GetOperatorsOfColumn(column: IQueryColumn): OperatorMap {
const operators: OperatorMap = new OperatorMap();
switch (column.Type) {
case QueryColumnType.Boolean: {
operators.push(
QueryOperatorType.Equal,
QueryOperandInputType.TwoOptions
);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.TwoOptions
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
break;
}
case QueryColumnType.Customer: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Customer);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Customer
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.CustomerMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.CustomerMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
break;
}
case QueryColumnType.DateTime: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.DateTime);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.DateTime
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.InFiscalPeriod,
QueryOperandInputType.DateTimePe
);
operators.push(
QueryOperatorType.InFiscalPeriodAndYear,
QueryOperandInputType.DateTimeFyPe
);
operators.push(
QueryOperatorType.InFiscalYear,
QueryOperandInputType.DateTimeFy
);
operators.push(
QueryOperatorType.InOrAfterFiscalPeriodAndYear,
QueryOperandInputType.DateTimeFyPe
);
operators.push(
QueryOperatorType.InOrBeforeFiscalPeriodAndYear,
QueryOperandInputType.DateTimeFyPe
);
operators.push(QueryOperatorType.Last7Days, QueryOperandInputType.None);
operators.push(
QueryOperatorType.LastFiscalPeriod,
QueryOperandInputType.None
);
operators.push(
QueryOperatorType.LastFiscalYear,
QueryOperandInputType.None
);
operators.push(QueryOperatorType.LastMonth, QueryOperandInputType.None);
operators.push(QueryOperatorType.LastWeek, QueryOperandInputType.None);
operators.push(
QueryOperatorType.LastXDays,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LastXFiscalPeriods,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LastXFiscalYears,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LastXHours,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LastXMonths,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LastXWeeks,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LastXYears,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LastYear,
QueryOperandInputType.Integer
);
operators.push(QueryOperatorType.Next7Days, QueryOperandInputType.None);
operators.push(
QueryOperatorType.NextFiscalPeriod,
QueryOperandInputType.None
);
operators.push(
QueryOperatorType.NextFiscalYear,
QueryOperandInputType.None
);
operators.push(QueryOperatorType.NextMonth, QueryOperandInputType.None);
operators.push(QueryOperatorType.NextWeek, QueryOperandInputType.None);
operators.push(
QueryOperatorType.NextXDays,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.NextXFiscalPeriods,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.NextXFiscalYears,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.NextXHours,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.NextXMonths,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.NextXWeeks,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.NextXYears,
QueryOperandInputType.Integer
);
operators.push(QueryOperatorType.NextYear, QueryOperandInputType.None);
operators.push(
QueryOperatorType.OlderThanXYears,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.OlderThanXMonths,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.OlderThanXWeeks,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.OlderThanXDays,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.OlderThanXHours,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.OlderThanXMinutes,
QueryOperandInputType.Integer
);
operators.push(QueryOperatorType.On, QueryOperandInputType.DateTime);
operators.push(
QueryOperatorType.OnOrAfter,
QueryOperandInputType.DateTime
);
operators.push(
QueryOperatorType.OnOrBefore,
QueryOperandInputType.DateTime
);
operators.push(
QueryOperatorType.ThisFiscalPeriod,
QueryOperandInputType.None
);
operators.push(
QueryOperatorType.ThisFiscalYear,
QueryOperandInputType.None
);
operators.push(QueryOperatorType.ThisMonth, QueryOperandInputType.None);
operators.push(QueryOperatorType.ThisWeek, QueryOperandInputType.None);
operators.push(QueryOperatorType.ThisYear, QueryOperandInputType.None);
operators.push(QueryOperatorType.Today, QueryOperandInputType.None);
operators.push(QueryOperatorType.Tomorrow, QueryOperandInputType.None);
operators.push(QueryOperatorType.Yesterday, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotOn, QueryOperandInputType.DateTime);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
operators.push(
QueryOperatorType.GreaterThan,
QueryOperandInputType.DateTime
);
operators.push(
QueryOperatorType.GreaterEqual,
QueryOperandInputType.DateTime
);
operators.push(
QueryOperatorType.LessThan,
QueryOperandInputType.DateTime
);
operators.push(
QueryOperatorType.LessEqual,
QueryOperandInputType.DateTime
);
break;
}
case QueryColumnType.Decimal: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Decimal);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Decimal
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.DecimalMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.DecimalMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
operators.push(
QueryOperatorType.Between,
QueryOperandInputType.DecimalRange
);
operators.push(
QueryOperatorType.NotBetween,
QueryOperandInputType.DecimalRange
);
operators.push(
QueryOperatorType.GreaterThan,
QueryOperandInputType.Decimal
);
operators.push(
QueryOperatorType.GreaterEqual,
QueryOperandInputType.Decimal
);
operators.push(
QueryOperatorType.LessThan,
QueryOperandInputType.Decimal
);
operators.push(
QueryOperatorType.LessEqual,
QueryOperandInputType.Decimal
);
break;
}
case QueryColumnType.Double: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Double);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Double
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.DoubleMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.DoubleMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
operators.push(
QueryOperatorType.Between,
QueryOperandInputType.DoubleRange
);
operators.push(
QueryOperatorType.NotBetween,
QueryOperandInputType.DoubleRange
);
operators.push(
QueryOperatorType.GreaterThan,
QueryOperandInputType.Double
);
operators.push(
QueryOperatorType.GreaterEqual,
QueryOperandInputType.Double
);
operators.push(
QueryOperatorType.LessThan,
QueryOperandInputType.Double
);
operators.push(
QueryOperatorType.LessEqual,
QueryOperandInputType.Double
);
break;
}
case QueryColumnType.Integer: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Integer);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.IntegerMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.IntegerMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
operators.push(
QueryOperatorType.Between,
QueryOperandInputType.IntegerRange
);
operators.push(
QueryOperatorType.NotBetween,
QueryOperandInputType.IntegerRange
);
operators.push(
QueryOperatorType.GreaterThan,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.GreaterEqual,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LessThan,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LessEqual,
QueryOperandInputType.Integer
);
break;
}
case QueryColumnType.Lookup: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Lookup);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Lookup
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.LookupMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.LookupMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
break;
}
case QueryColumnType.Memo: {
operators.push(
QueryOperatorType.Equal,
QueryOperandInputType.Paragraph
);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Paragraph
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.StringMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.StringMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.Paragraph
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.Paragraph
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.Paragraph
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.Paragraph
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.Paragraph
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.Paragraph
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.Paragraph);
operators.push(
QueryOperatorType.NotLike,
QueryOperandInputType.Paragraph
);
break;
}
case QueryColumnType.Money: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Decimal);
operators.push(QueryOperatorType.NotEqual, QueryOperandInputType.Decimal);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.DecimalMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.DecimalMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
operators.push(
QueryOperatorType.Between,
QueryOperandInputType.DecimalRange
);
operators.push(
QueryOperatorType.NotBetween,
QueryOperandInputType.DecimalRange
);
operators.push(
QueryOperatorType.GreaterThan,
QueryOperandInputType.Decimal
);
operators.push(
QueryOperatorType.GreaterEqual,
QueryOperandInputType.Decimal
);
operators.push(
QueryOperatorType.LessThan,
QueryOperandInputType.Decimal
);
operators.push(
QueryOperatorType.LessEqual,
QueryOperandInputType.Decimal
);
break;
}
case QueryColumnType.Owner: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Owner);
operators.push(QueryOperatorType.NotEqual, QueryOperandInputType.Owner);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.OwnerMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.OwnerMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.EqualUserId,
QueryOperandInputType.User
);
operators.push(
QueryOperatorType.NotEqualUserId,
QueryOperandInputType.User
);
operators.push(
QueryOperatorType.EqualUserOrUserHierarchy,
QueryOperandInputType.User
);
operators.push(
QueryOperatorType.EqualUserOrUserHierarchyAndTeams,
QueryOperandInputType.UserTeamMultiple
);
operators.push(
QueryOperatorType.EqualUserOrUserTeams,
QueryOperandInputType.UserTeamMultiple
);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
break;
}
case QueryColumnType.PartyList: {
operators.push(
QueryOperatorType.Equal,
QueryOperandInputType.PartyList
);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.PartyList
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.PartyListMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.PartyListMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
break;
}
case QueryColumnType.Picklist: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Options);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Options
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.OptionsMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.OptionsMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
operators.push(
QueryOperatorType.Between,
QueryOperandInputType.IntegerRange
);
operators.push(
QueryOperatorType.NotBetween,
QueryOperandInputType.IntegerRange
);
operators.push(
QueryOperatorType.GreaterThan,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.GreaterEqual,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LessThan,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LessEqual,
QueryOperandInputType.Integer
);
break;
}
case QueryColumnType.State: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Options);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Options
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.OptionsMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.OptionsMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
operators.push(
QueryOperatorType.Between,
QueryOperandInputType.IntegerRange
);
operators.push(
QueryOperatorType.NotBetween,
QueryOperandInputType.IntegerRange
);
operators.push(
QueryOperatorType.GreaterThan,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.GreaterEqual,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LessThan,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LessEqual,
QueryOperandInputType.Integer
);
break;
}
case QueryColumnType.Status: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Options);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Options
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.OptionsMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.OptionsMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
operators.push(
QueryOperatorType.Between,
QueryOperandInputType.IntegerRange
);
operators.push(
QueryOperatorType.NotBetween,
QueryOperandInputType.IntegerRange
);
operators.push(
QueryOperatorType.GreaterThan,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.GreaterEqual,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LessThan,
QueryOperandInputType.Integer
);
operators.push(
QueryOperatorType.LessEqual,
QueryOperandInputType.Integer
);
break;
}
case QueryColumnType.String: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.String);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.StringMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.StringMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
break;
}
case QueryColumnType.Uniqueidentifier: {
operators.push(QueryOperatorType.Equal, QueryOperandInputType.Lookup);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.Lookup
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.LookupMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.LookupMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(QueryOperatorType.Above, QueryOperandInputType.Lookup);
operators.push(
QueryOperatorType.AboveOrEqual,
QueryOperandInputType.Lookup
);
operators.push(QueryOperatorType.Under, QueryOperandInputType.Lookup);
operators.push(
QueryOperatorType.UnderOrEqual,
QueryOperandInputType.Lookup
);
operators.push(
QueryOperatorType.NotUnder,
QueryOperandInputType.Lookup
);
operators.push(
QueryOperatorType.EqualBusinessId,
QueryOperandInputType.Lookup
);
operators.push(
QueryOperatorType.EqualUserId,
QueryOperandInputType.Lookup
);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
break;
}
case QueryColumnType.CalendarRules: {
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
break;
}
case QueryColumnType.Virtual: {
break;
}
case QueryColumnType.BigInt: {
operators.push(
QueryOperatorType.Equal,
QueryOperandInputType.BigInteger
);
operators.push(
QueryOperatorType.NotEqual,
QueryOperandInputType.BigInteger
);
operators.push(
QueryOperatorType.In,
QueryOperandInputType.BigIntegerMultiple
);
operators.push(
QueryOperatorType.NotIn,
QueryOperandInputType.BigIntegerMultiple
);
operators.push(QueryOperatorType.Null, QueryOperandInputType.None);
operators.push(QueryOperatorType.NotNull, QueryOperandInputType.None);
operators.push(
QueryOperatorType.BeginsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotBeginWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.Contains,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotContain,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.EndsWith,
QueryOperandInputType.String
);
operators.push(
QueryOperatorType.DoesNotEndWith,
QueryOperandInputType.String
);
operators.push(QueryOperatorType.Like, QueryOperandInputType.String);
operators.push(QueryOperatorType.NotLike, QueryOperandInputType.String);
operators.push(
QueryOperatorType.Between,
QueryOperandInputType.BigIntegerRange
);
operators.push(
QueryOperatorType.NotBetween,
QueryOperandInputType.BigIntegerRange
);
operators.push(
QueryOperatorType.GreaterThan,
QueryOperandInputType.BigInteger
);
operators.push(
QueryOperatorType.GreaterEqual,
QueryOperandInputType.BigInteger
);
operators.push(
QueryOperatorType.LessThan,
QueryOperandInputType.BigInteger
);
operators.push(
QueryOperatorType.LessEqual,
QueryOperandInputType.BigInteger
);
break;
}
case QueryColumnType.ManagedProperty: {
break;
}
case QueryColumnType.EntityName: {
break;
}
}
return operators;
}
public GetInputParentType(inputType: QueryOperandInputType): QueryOperandType {
switch (inputType) {
case QueryOperandInputType.Integer:
case QueryOperandInputType.IntegerMultiple:
case QueryOperandInputType.IntegerRange:
case QueryOperandInputType.BigInteger:
case QueryOperandInputType.BigIntegerMultiple:
case QueryOperandInputType.BigIntegerRange:
case QueryOperandInputType.Decimal:
case QueryOperandInputType.DecimalMultiple:
case QueryOperandInputType.DecimalRange:
case QueryOperandInputType.Double:
case QueryOperandInputType.DoubleMultiple:
case QueryOperandInputType.DoubleRange:
return QueryOperandType.Number;
case QueryOperandInputType.String:
case QueryOperandInputType.StringMultiple:
case QueryOperandInputType.Paragraph:
return QueryOperandType.String;
case QueryOperandInputType.DateTime:
case QueryOperandInputType.DateTimeFy:
case QueryOperandInputType.DateTimePe:
case QueryOperandInputType.DateTimeFyPe:
return QueryOperandType.DateTime;
case QueryOperandInputType.Lookup:
case QueryOperandInputType.LookupMultiple:
case QueryOperandInputType.Customer:
case QueryOperandInputType.CustomerMultiple:
case QueryOperandInputType.Owner:
case QueryOperandInputType.OwnerMultiple:
case QueryOperandInputType.PartyList:
case QueryOperandInputType.PartyListMultiple:
case QueryOperandInputType.User:
case QueryOperandInputType.UserTeam:
case QueryOperandInputType.UserTeamMultiple:
return QueryOperandType.Lookup;
case QueryOperandInputType.TwoOptions: {
return QueryOperandType.TwoOptions;
}
case QueryOperandInputType.Options:
case QueryOperandInputType.OptionsMultiple:
return QueryOperandType.Options;
default: {
return QueryOperandType.None;
}
}
}
//#region helpers
private readLabel(metaRecord: any): string {
try {
const disp = metaRecord.DisplayName as DisplayName;
return disp.UserLocalizedLabel.Label;
} catch {
let label = null;
for (let i = 0; i < metaRecord.DisplayName.LocalizedLabels.length; i++) {
if (metaRecord.DisplayName.LocalizedLabels[i].LanguageCode === 1033) {
label = metaRecord.DisplayName.LocalizedLabels[i].Label;
}
}
if (label === null) {
if (metaRecord.DisplayName.LocalizedLabels.length > 0) {
label = metaRecord.DisplayName.LocalizedLabels[0].Label;
} else {
label = metaRecord.LogicalName;
}
}
return label;
}
}
private readOption(att: XrmMetaAttribute): IQueryOption[] {
try {
return att.OptionSet.Options.map(op => {
return {
Key: this.readOptionLabel(op),
Value: op.Value
} as IQueryOption;
});
} catch {
return [];
}
}
private readOptionLabel(metaRecord: any): string {
try {
const disp = metaRecord.DisplayName as DisplayName;
return disp.UserLocalizedLabel.Label;
} catch {
let label = null;
for (let i = 0; i < metaRecord.Label.LocalizedLabels.length; i++) {
if (metaRecord.Label.LocalizedLabels[i].LanguageCode === 1033) {
label = metaRecord.Label.LocalizedLabels[i].Label;
}
}
if (label === null) {
if (metaRecord.Label.LocalizedLabels.length > 0) {
label = metaRecord.Label.LocalizedLabels[0].Label;
} else {
label = "Option #";
}
}
return label;
}
}
private readAttributeType(type: string): QueryColumnType {
switch (type) {
case "Lookup": {
return QueryColumnType.Lookup;
}
case "State": {
return QueryColumnType.State;
}
case "Memo": {
return QueryColumnType.Memo;
}
case "Boolean": {
return QueryColumnType.Boolean;
}
case "String": {
return QueryColumnType.String;
}
case "Integer": {
return QueryColumnType.Integer;
}
case "DateTime": {
return QueryColumnType.DateTime;
}
case "Status": {
return QueryColumnType.Status;
}
case "Uniqueidentifier": {
return QueryColumnType.Uniqueidentifier;
}
case "Picklist": {
return QueryColumnType.Picklist;
}
case "Owner": {
return QueryColumnType.Owner;
}
case "BigInt": {
return QueryColumnType.BigInt;
}
case "EntityName": {
return QueryColumnType.EntityName;
}
case "Virtual": {
return QueryColumnType.Virtual;
}
case "Decimal": {
return QueryColumnType.Decimal;
}
case "ManagedProperty": {
return QueryColumnType.ManagedProperty;
}
case "Customer": {
return QueryColumnType.Customer;
}
case "PartyList": {
return QueryColumnType.PartyList;
}
case "Double": {
return QueryColumnType.Double;
}
case "Money": {
return QueryColumnType.Money;
}
case "CalendarRules": {
return QueryColumnType.CalendarRules;
}
default: {
return QueryColumnType.None;
}
}
}
private IsLocal(): boolean {
return (
window.location.hostname === "localhost" ||
window.location.hostname === "127.0.01"
);
}
private getUrl() {
return this.clientUrl || window.location.hostname;
}
//#endregion
//#region internals
private RetrieveAllEntities(
successCallBack,
errorCallBack
) {
const _this = this;
if (typeof successCallBack !== "function") {
throw new Error(
"SDK.Metadata.RetrieveAllEntities successCallBack must be a function."
);
}
if (typeof errorCallBack !== "function") {
throw new Error(
"SDK.Metadata.RetrieveAllEntities errorCallBack must be a function."
);
}
const entityFiltersValue = this._evaluateEntityFilters(1);
const request = [
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">',
// Allows retrieval if ImageAttributeMetadata objects
'<soapenv:Header><a:SdkClientVersion xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts">7.0</a:SdkClientVersion></soapenv:Header>',
"<soapenv:Body>",
'<Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">',
'<request i:type="a:RetrieveAllEntitiesRequest" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts">',
'<a:Parameters xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic">',
"<a:KeyValuePairOfstringanyType>",
"<b:key>EntityFilters</b:key>",
'<b:value i:type="c:EntityFilters" xmlns:c="http://schemas.microsoft.com/xrm/2011/Metadata">' +
_this._xmlEncode(entityFiltersValue) +
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>RetrieveAsIfPublished</b:key>",
'<b:value i:type="c:boolean" xmlns:c="http://www.w3.org/2001/XMLSchema">' +
_this._xmlEncode(true.toString()) +
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"</a:Parameters>",
'<a:RequestId i:nil="true" />',
"<a:RequestName>RetrieveAllEntities</a:RequestName>",
"</request>",
"</Execute>",
"</soapenv:Body>",
"</soapenv:Envelope>"
].join("");
const req = new XMLHttpRequest();
req.open(
"POST",
_this.getUrl() + "/XRMServices/2011/Organization.svc/web",
true
);
try {
req.responseType = "msxml-document" as any;
} catch (e) {}
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader(
"SOAPAction",
"http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute"
);
req.onreadystatechange = function() {
const __this = _this;
if (req.readyState === 4 /* complete */) {
req.onreadystatechange = null; // Addresses potential memory leak issue with IE
if (req.status === 200) {
// Success
const doc = req.responseXML;
try {
__this._setSelectionNamespaces(doc);
} catch (e) {}
const entityMetadataNodes = __this._selectNodes(doc, "//c:EntityMetadata");
const entityMetadataCollection: XrmMetaEntity[] = [];
for (let i = 0; i < entityMetadataNodes.length; i++) {
const a = __this._objectifyNode(entityMetadataNodes[i]);
a._type = "EntityMetadata";
entityMetadataCollection.push(a);
}
successCallBack(entityMetadataCollection);
} else {
errorCallBack(__this._getError(req));
}
}
};
req.send(request);
}
private RetrieveAttributes(
LogicalName,
successCallBack,
errorCallBack
) {
let MetadataId = null;
const _this = this;
if (LogicalName == null && MetadataId == null) {
throw new Error(
"SDK.Metadata.RetrieveEntity requires either the LogicalName or MetadataId parameter not be null."
);
}
if (LogicalName != null) {
if (typeof LogicalName !== "string") {
throw new Error(
"SDK.Metadata.RetrieveEntity LogicalName must be a string value."
);
}
MetadataId = "00000000-0000-0000-0000-000000000000";
}
if (MetadataId != null && LogicalName == null) {
if (typeof MetadataId !== "string") {
throw new Error(
"SDK.Metadata.RetrieveEntity MetadataId must be a string value."
);
}
}
if (typeof successCallBack !== "function") {
throw new Error(
"SDK.Metadata.RetrieveEntity successCallBack must be a function."
);
}
if (typeof errorCallBack !== "function") {
throw new Error(
"SDK.Metadata.RetrieveEntity errorCallBack must be a function."
);
}
const entityFiltersValue = _this._evaluateEntityFilters(2);
let entityLogicalNameValueNode = "";
if (LogicalName == null) {
entityLogicalNameValueNode = '<b:value i:nil="true" />';
} else {
entityLogicalNameValueNode =
'<b:value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">' +
_this._xmlEncode(LogicalName.toLowerCase()) +
"</b:value>";
}
const request = [
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">',
// Allows retrieval if ImageAttributeMetadata objects
'<soapenv:Header><a:SdkClientVersion xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts">6.0</a:SdkClientVersion></soapenv:Header>',
"<soapenv:Body>",
'<Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">',
'<request i:type="a:RetrieveEntityRequest" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts">',
'<a:Parameters xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic">',
"<a:KeyValuePairOfstringanyType>",
"<b:key>EntityFilters</b:key>",
'<b:value i:type="c:EntityFilters" xmlns:c="http://schemas.microsoft.com/xrm/2011/Metadata">' +
_this._xmlEncode(entityFiltersValue) +
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>MetadataId</b:key>",
'<b:value i:type="ser:guid" xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/">' +
_this._xmlEncode(MetadataId) +
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>RetrieveAsIfPublished</b:key>",
'<b:value i:type="c:boolean" xmlns:c="http://www.w3.org/2001/XMLSchema">' +
_this._xmlEncode(true.toString()) +
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>LogicalName</b:key>",
entityLogicalNameValueNode,
"</a:KeyValuePairOfstringanyType>",
"</a:Parameters>",
'<a:RequestId i:nil="true" />',
"<a:RequestName>RetrieveEntity</a:RequestName>",
"</request>",
"</Execute>",
"</soapenv:Body>",
"</soapenv:Envelope>"
].join("");
const req = new XMLHttpRequest();
req.open(
"POST",
_this.getUrl() + "/XRMServices/2011/Organization.svc/web",
true
);
try {
req.responseType = "msxml-document" as any;
} catch (e) {}
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader(
"SOAPAction",
"http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute"
);
req.onreadystatechange = function() {
const __this = _this;
if (req.readyState === 4 /* complete */) {
req.onreadystatechange = null; // Addresses potential memory leak issue with IE
if (req.status === 200) {
const doc = req.responseXML;
try {
__this._setSelectionNamespaces(doc);
} catch (e) {}
const a: XrmMetaEntity = __this._objectifyNode(__this._selectSingleNode(doc, "//b:value"));
a._type = "EntityMetadata";
successCallBack(a.Attributes);
} else {
// Failure
errorCallBack(__this._getError(req));
}
}
};
req.send(request);
}
private RetrieveRelations(
LogicalName,
successCallBack,
errorCallBack
) {
let MetadataId = null;
const _this = this;
if (LogicalName == null && MetadataId == null) {
throw new Error(
"SDK.Metadata.RetrieveEntity requires either the LogicalName or MetadataId parameter not be null."
);
}
if (LogicalName != null) {
if (typeof LogicalName !== "string") {
throw new Error(
"SDK.Metadata.RetrieveEntity LogicalName must be a string value."
);
}
MetadataId = "00000000-0000-0000-0000-000000000000";
}
if (MetadataId != null && LogicalName == null) {
if (typeof MetadataId !== "string") {
throw new Error(
"SDK.Metadata.RetrieveEntity MetadataId must be a string value."
);
}
}
if (typeof successCallBack !== "function") {
throw new Error(
"SDK.Metadata.RetrieveEntity successCallBack must be a function."
);
}
if (typeof errorCallBack !== "function") {
throw new Error(
"SDK.Metadata.RetrieveEntity errorCallBack must be a function."
);
}
const entityFiltersValue = _this._evaluateEntityFilters(8);
let entityLogicalNameValueNode = "";
if (LogicalName == null) {
entityLogicalNameValueNode = '<b:value i:nil="true" />';
} else {
entityLogicalNameValueNode =
'<b:value i:type="c:string" xmlns:c="http://www.w3.org/2001/XMLSchema">' +
_this._xmlEncode(LogicalName.toLowerCase()) +
"</b:value>";
}
const request = [
'<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">',
// Allows retrieval if ImageAttributeMetadata objects
'<soapenv:Header><a:SdkClientVersion xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts">6.0</a:SdkClientVersion></soapenv:Header>',
"<soapenv:Body>",
'<Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">',
'<request i:type="a:RetrieveEntityRequest" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts">',
'<a:Parameters xmlns:b="http://schemas.datacontract.org/2004/07/System.Collections.Generic">',
"<a:KeyValuePairOfstringanyType>",
"<b:key>EntityFilters</b:key>",
'<b:value i:type="c:EntityFilters" xmlns:c="http://schemas.microsoft.com/xrm/2011/Metadata">' +
_this._xmlEncode(entityFiltersValue) +
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>MetadataId</b:key>",
'<b:value i:type="ser:guid" xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/">' +
_this._xmlEncode(MetadataId) +
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>RetrieveAsIfPublished</b:key>",
'<b:value i:type="c:boolean" xmlns:c="http://www.w3.org/2001/XMLSchema">' +
_this._xmlEncode(true.toString()) +
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>LogicalName</b:key>",
entityLogicalNameValueNode,
"</a:KeyValuePairOfstringanyType>",
"</a:Parameters>",
'<a:RequestId i:nil="true" />',
"<a:RequestName>RetrieveEntity</a:RequestName>",
"</request>",
"</Execute>",
"</soapenv:Body>",
"</soapenv:Envelope>"
].join("");
const req = new XMLHttpRequest();
req.open(
"POST",
_this.getUrl() + "/XRMServices/2011/Organization.svc/web",
true
);
try {
req.responseType = "msxml-document" as any;
} catch (e) {}
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader(
"SOAPAction",
"http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute"
);
req.onreadystatechange = function() {
const __this = _this;
if (req.readyState === 4 /* complete */) {
req.onreadystatechange = null; // Addresses potential memory leak issue with IE
if (req.status === 200) {
const doc = req.responseXML;
try {
__this._setSelectionNamespaces(doc);
} catch (e) {}
const a: XrmMetaEntity = __this._objectifyNode(__this._selectSingleNode(doc, "//b:value"));
a._type = "EntityMetadata";
successCallBack(a);
} else {
// Failure
errorCallBack(__this._getError(req));
}
}
};
req.send(request);
}
private _getError(resp) {
const _this = this;
if (resp.status === 12029) {
return new Error("The attempt to connect to the server failed.");
}
if (resp.status === 12007) {
return new Error("The server name could not be resolved.");
}
const faultXml = resp.responseXML;
let errorMessage = "Unknown (unable to parse the fault)";
let faultstring = null;
let ErrorCode = null;
if (typeof faultXml === "object") {
const bodyNode = faultXml.firstChild.firstChild;
// Retrieve the fault node
for (let i = 0; i < bodyNode.childNodes.length; i++) {
const node = bodyNode.childNodes[i];
// NOTE: This comparison does not handle the case where the XML namespace changes
if ("s:Fault" === node.nodeName) {
for (let j = 0; j < node.childNodes.length; j++) {
const testNode = node.childNodes[j];
if ("faultstring" === testNode.nodeName) {
faultstring = _this._getNodeText(testNode);
}
if ("detail" === testNode.nodeName) {
for (let k = 0; k < testNode.childNodes.length; k++) {
const orgServiceFault = testNode.childNodes[k];
if ("OrganizationServiceFault" === orgServiceFault.nodeName) {
for (let l = 0; l < orgServiceFault.childNodes.length; l++) {
const ErrorCodeNode = orgServiceFault.childNodes[l];
if ("ErrorCode" === ErrorCodeNode.nodeName) {
ErrorCode = _this._getNodeText(ErrorCodeNode);
break;
}
}
}
}
}
}
break;
}
}
}
if (ErrorCode != null && faultstring != null) {
errorMessage = "Error Code:" + ErrorCode + " Message: " + faultstring;
} else {
if (faultstring != null) {
errorMessage = faultstring;
}
}
return new Error(errorMessage);
}
private _evaluateEntityFilters(EntityFilters) {
const entityFilterArray = [];
if ((1 & EntityFilters) === 1) {
entityFilterArray.push("Entity");
}
if ((2 & EntityFilters) === 2) {
entityFilterArray.push("Attributes");
}
if ((4 & EntityFilters) === 4) {
entityFilterArray.push("Privileges");
}
if ((8 & EntityFilters) === 8) {
entityFilterArray.push("Relationships");
}
return entityFilterArray.join(" ");
}
private _isMetadataArray(elementName) {
const _this = this;
for (let i = 0; i < _this._arrayElements.length; i++) {
if (elementName === _this._arrayElements[i]) {
return true;
}
}
return false;
}
private _objectifyNode(node) {
const _this = this;
// Check for null
if (node.attributes != null && node.attributes.length === 1) {
if (
node.attributes.getNamedItem("i:nil") != null &&
node.attributes.getNamedItem("i:nil").nodeValue === "true"
) {
return null;
}
}
// Check if it is a value
if (node.firstChild != null && node.firstChild.nodeType === 3) {
const nodeName = _this._getNodeName(node);
switch (nodeName) {
// Integer Values
case "ActivityTypeMask":
case "ObjectTypeCode":
case "ColumnNumber":
case "DefaultFormValue":
case "MaxValue":
case "MinValue":
case "MaxLength":
case "Order":
case "Precision":
case "PrecisionSource":
case "LanguageCode":
return parseInt(node.firstChild.nodeValue, 10);
// Boolean values
case "AutoRouteToOwnerQueue":
case "CanBeChanged":
case "CanTriggerWorkflow":
case "IsActivity":
case "IsAIRUpdated":
case "IsActivityParty":
case "IsAvailableOffline":
case "IsChildEntity":
case "IsCustomEntity":
case "IsCustomOptionSet":
case "IsDocumentManagementEnabled":
case "IsEnabledForCharts":
case "IsGlobal":
case "IsImportable":
case "IsIntersect":
case "IsManaged":
case "IsReadingPaneEnabled":
case "IsValidForAdvancedFind":
case "CanBeSecuredForCreate":
case "CanBeSecuredForRead":
case "CanBeSecuredForUpdate":
case "IsCustomAttribute":
case "IsManaged":
case "IsPrimaryId":
case "IsPrimaryName":
case "IsSecured":
case "IsValidForCreate":
case "IsValidForRead":
case "IsValidForUpdate":
case "IsCustomRelationship":
case "CanBeBasic":
case "CanBeDeep":
case "CanBeGlobal":
case "CanBeLocal":
return node.firstChild.nodeValue === "true" ? true : false;
// OptionMetadata.Value and BooleanManagedProperty.Value and AttributeRequiredLevelManagedProperty.Value
case "Value":
// BooleanManagedProperty.Value
if (
node.firstChild.nodeValue === "true" ||
node.firstChild.nodeValue === "false"
) {
return node.firstChild.nodeValue === "true" ? true : false;
}
// AttributeRequiredLevelManagedProperty.Value
if (
node.firstChild.nodeValue === "ApplicationRequired" ||
node.firstChild.nodeValue === "None" ||
node.firstChild.nodeValue === "Recommended" ||
node.firstChild.nodeValue === "SystemRequired"
) {
return node.firstChild.nodeValue;
}
const numberValue = parseInt(node.firstChild.nodeValue, 10);
if (isNaN(numberValue)) {
// FormatName.Value
return node.firstChild.nodeValue;
} else {
// OptionMetadata.Value
return numberValue;
}
break;
// String values
default:
return node.firstChild.nodeValue;
}
}
// Check if it is a known array
if (_this._isMetadataArray(_this._getNodeName(node))) {
const arrayValue = [];
for (let i = 0; i < node.childNodes.length; i++) {
let objectTypeName;
if (
node.childNodes[i].attributes != null &&
node.childNodes[i].attributes.getNamedItem("i:type") != null
) {
objectTypeName = node.childNodes[i].attributes
.getNamedItem("i:type")
.nodeValue.split(":")[1];
} else {
objectTypeName = _this._getNodeName(node.childNodes[i]);
}
const b = _this._objectifyNode(node.childNodes[i]);
b._type = objectTypeName;
arrayValue.push(b);
}
return arrayValue;
}
// Null entity description labels are returned as <label/> - not using i:nil = true;
if (node.childNodes.length === 0) {
return null;
}
// Otherwise return an object
const c: any = {};
if (node.attributes.getNamedItem("i:type") != null) {
c._type = node.attributes.getNamedItem("i:type").nodeValue.split(":")[1];
}
for (let i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].nodeType === 3) {
c[_this._getNodeName(node.childNodes[i])] = node.childNodes[i].nodeValue;
} else {
c[_this._getNodeName(node.childNodes[i])] = _this._objectifyNode(
node.childNodes[i]
);
}
}
return c;
}
private _selectNodes(node, XPathExpression) {
const _this = this;
if (typeof node.selectNodes !== "undefined") {
return node.selectNodes(XPathExpression);
} else {
const output = [];
const XPathResults = node.evaluate(
XPathExpression,
node,
_this._NSResolver,
XPathResult.ANY_TYPE,
null
);
let result = XPathResults.iterateNext();
while (result) {
output.push(result);
result = XPathResults.iterateNext();
}
return output;
}
}
private _selectSingleNode(node, xpathExpr) {
const _this = this;
if (typeof node.selectSingleNode !== "undefined") {
return node.selectSingleNode(xpathExpr);
} else {
const xpe = new XPathEvaluator();
const xPathNode = xpe.evaluate(
xpathExpr,
node,
_this._NSResolver,
XPathResult.FIRST_ORDERED_NODE_TYPE,
null
);
return xPathNode != null ? xPathNode.singleNodeValue : null;
}
}
private _selectSingleNodeText(node, xpathExpr) {
const _this = this;
const x = _this._selectSingleNode(node, xpathExpr);
if (_this._isNodeNull(x)) {
return null;
}
if (typeof x.text !== "undefined") {
return x.text;
} else {
return x.textContent;
}
}
private _getNodeText(node) {
if (typeof node.text !== "undefined") {
return node.text;
} else {
return node.textContent;
}
}
private _isNodeNull(node) {
if (node == null) {
return true;
}
if (
node.attributes.getNamedItem("i:nil") != null &&
node.attributes.getNamedItem("i:nil").value === "true"
) {
return true;
}
return false;
}
private _getNodeName(node) {
if (typeof node.baseName !== "undefined") {
return node.baseName;
} else {
return node.localName;
}
}
private _setSelectionNamespaces(doc) {
const namespaces = [
"xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'",
"xmlns:a='http://schemas.microsoft.com/xrm/2011/Contracts'",
"xmlns:i='http://www.w3.org/2001/XMLSchema-instance'",
"xmlns:b='http://schemas.datacontract.org/2004/07/System.Collections.Generic'",
"xmlns:c='http://schemas.microsoft.com/xrm/2011/Metadata'"
];
doc.setProperty("SelectionNamespaces", namespaces.join(" "));
}
private _NSResolver(prefix) {
const ns = {
s: "http://schemas.xmlsoap.org/soap/envelope/",
a: "http://schemas.microsoft.com/xrm/2011/Contracts",
i: "http://www.w3.org/2001/XMLSchema-instance",
b: "http://schemas.datacontract.org/2004/07/System.Collections.Generic",
c: "http://schemas.microsoft.com/xrm/2011/Metadata"
};
return ns[prefix] || null;
}
private _xmlEncode(strInput) {
let c;
let XmlEncode = "";
if (strInput == null) {
return null;
}
if (strInput === "") {
return "";
}
for (let cnt = 0; cnt < strInput.length; cnt++) {
c = strInput.charCodeAt(cnt);
if (
(c > 96 && c < 123) ||
(c > 64 && c < 91) ||
c === 32 ||
(c > 47 && c < 58) ||
c === 46 ||
c === 44 ||
c === 45 ||
c === 95
) {
XmlEncode = XmlEncode + String.fromCharCode(c);
} else {
XmlEncode = XmlEncode + "&#" + c + ";";
}
}
return XmlEncode;
}
//#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment