public Record GetItemById(string id, RecordFormat format)
 {
     return(_mapper.Map <RecordWithInverses>(_store.GetRecord(_store.CodeEntity(id)), options => options.Items["Format"] = format));
 }
Exemple #2
0
        // Новая реализация загрузки базы данных
        private void FillDb(IEnumerable <FogInfo> fogFlow)
        {
            // Пока каждый раз чистим базу данных
            Store.Clear();
            // Вычисление "важных" кодов
            var codRdftype = Store.CodeEntity("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); // Зафиксирован? 0;


            // Готовим битовый массив для отметки того, что хеш id уже "попадал" в этот бит
            int rang     = 24; // пока предполагается, что число записей (много) меньше 16 млн.
            int mask     = ~((-1) << rang);
            int baVolume = mask + 1;

            System.Collections.BitArray bitArr = new System.Collections.BitArray(baVolume);
            // Хеш-функция будет ограничена rang разрядами, массив и функция нужны только временно
            int Hash(string s) => s.GetHashCode() & mask;

            // Словарь, фиксирующий максимальную дату для заданного идентификатора, первая запись не учитывается
            Dictionary <string, DateTime> lastDefs = new Dictionary <string, DateTime>();

            // Первый проход сканирования фог-файлов. В этом проходе определяется набор повторно определенных записей и
            // формируется словарь lastDefs
            foreach (FogInfo fi in fogFlow)
            {
                switch (fi.Vid)
                {
                // Чтение фога
                case ".fog":
                {
                    fi.Fogx = XElement.Load(fi.Pth);
                    foreach (XElement xElement in fi.Fogx.Elements())
                    {
                        XElement record = ConvertXElement(xElement);
                        // Обработаем "странные" delete и replace
                        if (record.Name == ONames.fogi + "delete")
                        {
                            string idd = record.Attribute(ONames.rdfabout)?.Value ?? record.Attribute("id")?.Value;
                            // Если нет атрибута mT, временная отметка устанавливается максимальной, чтобы "забить" другие отметки
                            string mTvalue = record.Attribute("mT") == null
                                    ? DateTime.MaxValue.ToString(CultureInfo.InvariantCulture)
                                    : record.Attribute("mT")?.Value;

                            CheckAndSet(bitArr, Hash, lastDefs, idd, mTvalue);
                            continue;
                        }

                        if (record.Name == ONames.fogi + "substitute")
                        {
                            continue;                                                // пока не обрабатываем
                        }
                        string id = record.Attribute(ONames.rdfabout)?.Value;
                        CheckAndSet(bitArr, Hash, lastDefs, id, record.Attribute("mT")?.Value);
                    }

                    fi.Fogx = null;
                    break;
                }

                case ".fogp":
                    break;
                }
            }

            // Второй проход сканирования фог-файлов. В этом проходе, для каждого фога формируется поток записей в
            // объектном представлении, потом этот поток добавляется в store
            foreach (FogInfo fi in fogFlow)
            {
                switch (fi.Vid)
                {
                // Чтение фога
                case ".fog":
                case ".fogx":
                {
                    fi.Fogx = XElement.Load(fi.Pth);
                    IEnumerable <object> flow = fi.Fogx.Elements()
                                                .Select(xrec => ConvertXElement(xrec))
                                                // Обработаем delete и replace. delete доминирует (по времени), но в выходной поток ничего не попадает
                                                // substitute - не обрабатываем
                                                .Where(record => record.Name != ONames.fogi + "delete" &&
                                                       record.Name != ONames.fogi + "substitute")
                                                // Отфильтруем записи с малыми временами. т.е. если идентификатор есть в словаре, но он меньше.
                                                // Если он больше, то не фильтруем, а словарный вход корректируем
                                                .Where(record =>
                        {
                            var xAbout = record.Attribute(ONames.rdfabout);
                            if (xAbout == null)
                            {
                                return(true);
                            }
                            string id = xAbout.Value;
                            if (!lastDefs.ContainsKey(id))
                            {
                                return(true);
                            }
                            DateTime mT    = DateTime.MinValue;
                            string mTvalue = record.Attribute("mT")?.Value;
                            if (mTvalue != null)
                            {
                                mT = DateTime.Parse(mTvalue);
                            }
                            DateTime last = lastDefs[id];
                            if (mT < last)
                            {
                                return(false);               // пропускаем
                            }
                            if (mT == last)
                            {
                                return(true);                // берем
                            }
                            // if(mT > last) // берем и корректируем last
                            {
                                lastDefs.Remove(id);
                                lastDefs.Add(id, mT);
                                return(true);
                            }
                        })
                                                .Select(record =>
                        {
                            string id        = record.Attribute(ONames.rdfabout).Value;
                            int rec_type     = Store.CodeEntity(ONames.fog + record.Name.LocalName);
                            int id_ent       = Store.CodeEntity(id);
                            object[] orecord = new object[]
                            {
                                id_ent,
                                (new object[] { new object[] { codRdftype, rec_type } }).Concat(
                                    record.Elements().Where(el => el.Attribute(ONames.rdfresource) != null)
                                    .Select(subel =>
                                {
                                    int prop = Store.CodeEntity(
                                        subel.Name.NamespaceName + subel.Name.LocalName);
                                    return(new object[]
                                           { prop, Store.CodeEntity(subel.Attribute(ONames.rdfresource).Value) });
                                })).ToArray(),
                                record.Elements().Where(el => el.Attribute(ONames.rdfresource) == null)
                                .Select(subel =>
                                {
                                    int prop = Store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName);
                                    return(new object[] { prop, subel.Value });
                                })
                                .ToArray()
                            };
                            return(orecord);
                        });
                    Store.Load(flow);

                    fi.Fogx = null;
                    break;
                }

                case ".fogp":
                    break;
                }
            }

            Store.Build();
            Store.Flush();
            GC.Collect();
        }
        public TripleStoreProfile(TripleRecordStore store)
        {
            _store = store;
            // Вычисление "важных" кодов
            cod_rdftype = store.CodeEntity("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"); // Зафиксирован? 0;
            cod_delete  = store.CodeEntity("http://fogid.net/o/delete");
            cod_name    = store.CodeEntity("http://fogid.net/o/name");
            CreateMap <object, RecordField>().ConstructUsing((triples, context) =>
            {
                if (!(triples is object[] dup))
                {
                    return(null);
                }
                return(new RecordField()
                {
                    Property = store.Decode((int)dup[0]),
                    Value = (string)dup[1]
                });
            });
            CreateMap <object, RecordProperty>().ConstructUsing((triples, context) =>
            {
                if (!(triples is object[] dup))
                {
                    return(null);
                }
                return(new RecordProperty()
                {
                    Property = store.DecodeEntity((int)dup[0]),
                    Value = new Record()
                    {
                        Id = store.DecodeEntity((int)dup[1])
                    }
                });
            });
            CreateMap <object, RecordInverseProperty>().ConstructUsing((source, context) =>
            {
                if (!(source is object[] triples))
                {
                    return(null);
                }
                int cid        = (int)triples[0];
                object[] found = ((object[])triples[1]).Cast <object[]>().FirstOrDefault(dup => (int)dup[1] == cid);
                return(new RecordInverseProperty()
                {
                    Property = store.DecodeEntity((int)found[0]),
                    Value = new Record()
                    {
                        Id = store.DecodeEntity((int)triples[0])
                    }
                });
            });

            CreateMap <object, Record>().ConstructUsing((source, context) =>
            {
                if (!(source is object[] triples))
                {
                    return(null);
                }
                if (context.Options.Items["Format"] is RecordFormat format)
                {
                    //todo use format recursive
                    return(new Record()
                    {
                        Id = store.DecodeEntity((int)triples[0]),
                        Type = GetRecordType(source),
                        Fields = context.Mapper.Map <RecordField[]>(((object[])triples[2])),
                        Directs = context.Mapper.Map <RecordProperty[]>((object[])triples[1])
                    });
                }

                return(new Record()
                {
                    Id = store.DecodeEntity((int)triples[0]),
                    Type = GetRecordType(source),
                    Fields = context.Mapper.Map <RecordField[]>((object[])triples[2]),
                    Directs = context.Mapper.Map <RecordProperty[]>((object[])triples[1])
                });
            });
            CreateMap <object, RecordWithInverses>().ConstructUsing((source, context) =>
            {
                if (!(source is object[] triples))
                {
                    return(null);
                }
                return(new RecordWithInverses()
                {
                    Id = store.DecodeEntity((int)triples[0]),
                    Type = GetRecordType(source),
                    Fields = context.Mapper.Map <RecordField[]>((object[])triples[2]),
                    Directs = context.Mapper.Map <RecordProperty[]>((object[])triples[1]),
                    Inverses =
                        context.Mapper.Map <IEnumerable <RecordInverseProperty> >(store.GetRefers((int)triples[0]))
                        ?.ToArray()
                });
            });

            CreateMap <Record, XElement>().ConvertUsing((record, context) =>
            {
                if (record == null)
                {
                    return(null);
                }
                XElement xres = new XElement("record",
                                             new XAttribute("id", record.Id), record.Type == null ? null : new XAttribute("type", record.Type),
                                             record.Fields?.Select(dup => new XElement("field", new XAttribute("prop", dup.Property), dup.Value)),
                                             record.Directs?.Select(dup => new XElement("direct", new XAttribute("prop", dup.Property),
                                                                                        new XElement("record", new XAttribute("id", dup.Value.Id)))));

                return(xres);
            });
            CreateMap <RecordWithInverses, XElement>().ConvertUsing((record, context) => record == null
                ? null
                : new XElement("record",
                               new XAttribute("id", record.Id),
                               record.Type == null ? null : new XAttribute("type", record.Type),
                               record.Fields?.Select(dup =>
                                                     new XElement("field", new XAttribute("prop", dup.Property), dup.Value)),
                               record.Directs?.Select(dup => new XElement("direct", new XAttribute("prop", dup.Property),
                                                                          new XElement("record", new XAttribute("id", dup.Value.Id)))),
                               record.Inverses?.Select(dup => new XElement("direct", new XAttribute("prop", dup.Property),
                                                                           new XElement("record", new XAttribute("id", dup.Value.Id))))));


            // ============================== Редактирование ================================
            CreateMap <Record, object>().ConvertUsing((record, context) =>
            {
                int cid = store.CodeEntity(record.Id);
                return(new object[]
                {
                    cid,
                    Enumerable.Repeat(new object[] { cod_rdftype, store.CodeEntity(record.Type) }, 1)
                    .Concat(record.Directs
                            .Select(el => new object[]
                    {
                        store.CodeEntity(el.Property),
                        store.CodeEntity(el.Value.Id)
                    })).ToArray(),
                    record.Fields
                    .Select(el => new object[]
                            { store.CodeEntity(el.Property), el.Value }).ToArray()
                });
            });

            CreateMap <XElement, Record>().ConvertUsing((xRecord, context) =>
            {
                var xAbout = xRecord.Attribute("{http://www.w3.org/1999/02/22-rdf-syntax-ns#}about");
                if (xAbout == null)
                {
                    return(null);
                }
                var props = xRecord.Elements().Select(x =>
                                                      (x,
                                                       resource: x.Attribute("{http://www.w3.org/1999/02/22-rdf-syntax-ns#}resource"),
                                                       property: "http://fogid.net/o/" + x.Name.LocalName))
                            .GroupBy(el => el.resource != null)
                            .ToArray();
                string id = xAbout.Value;
                string tp = "http://fogid.net/o/" + xRecord.Name.LocalName;
                return(new Record()
                {
                    Id = id,
                    Type = tp,
                    Fields = props.Where(g => !g.Key).SelectMany(x => x)
                             .Select(el => new RecordField
                    {
                        Property = el.property,
                        Value = el.x.Value
                    })
                             .ToArray(),
                    Directs = props.Where(g => g.Key).SelectMany(x => x)
                              .Select(el => new RecordProperty
                    {
                        Property = el.property,
                        Value = new Record
                        {
                            Id = el.resource.Value
                        }
                    }).ToArray(),
                });
            });
        }
Exemple #4
0
        public override void LoadXFlow(IEnumerable <XElement> xflow, Dictionary <string, string> orig_ids)
        {
            IEnumerable <object> flow = xflow.Select(record =>
            {
                string id = record.Attribute(ONames.rdfabout).Value;
                // Корректируем идентификатор
                if (orig_ids.TryGetValue(id, out string idd))
                {
                    id = idd;
                }
                int rec_type     = store.CodeEntity(ONames.fog + record.Name.LocalName);
                int id_ent       = store.CodeEntity(id);
                object[] orecord = new object[] {
                    id_ent,
                    (new object[] { new object[] { store.cod_rdftype, rec_type } }).Concat(
                        record.Elements().Where(el => el.Attribute(ONames.rdfresource) != null)
                        .Select(subel =>
                    {
                        int prop        = store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName);
                        string resource = subel.Attribute(ONames.rdfresource).Value;
                        if (orig_ids.TryGetValue(resource, out string res))
                        {
                            if (res != null)
                            {
                                resource = res;
                            }
                        }
                        return(new object[] { prop, store.CodeEntity(resource) });
                    })).ToArray()
                    ,
                    record.Elements().Where(el => el.Attribute(ONames.rdfresource) == null)
                    .Select(subel =>
                    {
                        int prop    = store.CodeEntity(subel.Name.NamespaceName + subel.Name.LocalName);
                        var xlang   = subel.Attribute("{http://www.w3.org/XML/1998/namespace}lang");
                        string lang = xlang == null ? "" : xlang.Value;
                        return(new object[] { prop, subel.Value, lang });
                    })
                    .ToArray()
                };
                return(orecord);
            });

            store.Load(flow);
        }