// Facts encodes the schema as facts. This is primarily used for programmatically // creating a schema and then writing the facts to storage for later use. func (s *Schema) Facts() origins.Facts { var ( err error attr *Attribute fact *origins.Fact facts origins.Facts buf = origins.NewBuffer(nil) entity *origins.Ident ) for _, attr = range s.attrs { entity = &origins.Ident{ Domain: attr.Domain, Name: attr.Name, } if facts, err = origins.Reflect(attr); err != nil { panic(err) } for _, fact = range facts { fact.Domain = s.Domain fact.Entity = entity // Fill in the defaults. if fact.Attribute.Domain == "" { fact.Attribute.Domain = fact.Domain } buf.Write(fact) } } return buf.Facts() }
// defaults fills in the default values for the fact. func (tx *Transaction) defaults(f *origins.Fact) error { if f.Domain == "" { if tx.options.DefaultDomain == "" { return ErrNoDomain } f.Domain = tx.options.DefaultDomain } // Default to fact domain. if f.Entity.Domain == "" { f.Entity.Domain = f.Domain } if f.Attribute.Domain == "" { f.Attribute.Domain = f.Domain } // Set fact time to the transaction time if flagged to do so. if f.Time.IsZero() && tx.options.SetDefaultTime { f.Time = tx.StartTime } return nil }
// unmarshalFact decodes a fact from it's binary representation. The domain and // transaction ID are passed in since they are not encoded with the fact itself. // This is because facts are stored relative to a domain and a transaction. func unmarshalFact(m *ProtoFact, b []byte, d string, t uint64, f *origins.Fact) error { m.Reset() if err := proto.Unmarshal(b, m); err != nil { return err } f.Domain = d f.Transaction = t f.Entity = &origins.Ident{ Domain: m.GetEntityDomain(), Name: m.GetEntity(), } f.Attribute = &origins.Ident{ Domain: m.GetAttributeDomain(), Name: m.GetAttribute(), } f.Value = &origins.Ident{ Domain: m.GetValueDomain(), Name: m.GetValue(), } f.Time = chrono.MicroTime(m.GetTime()) if m.GetAdded() { f.Operation = origins.Assertion } else { f.Operation = origins.Retraction } return nil }
// macro takes a fact and resolves the macro. func (tx *Transaction) macro(fact *origins.Fact) error { // Do not process facts for the macros themselves. if fact.Domain == origins.MacrosDomain { return nil } // Entity-based macro. if fact.Entity.Domain == origins.MacrosDomain { switch fact.Entity.Name { // Facts about the domain. case "domain": fact.Entity.Name = fact.Domain fact.Domain = origins.DomainsDomain fact.Entity.Domain = "" // Facts about the transaction. case "tx": fact.Domain = origins.TransactionsDomain fact.Entity.Domain = "" fact.Entity.Name = fmt.Sprint(tx.ID) default: return fmt.Errorf("transactor(%d): unknown entity macro: %s", tx.ID, fact.Entity.Name) } } // Value-based macro. if fact.Value.Domain == origins.MacrosDomain { switch fact.Value.Name { // Set the value to the transaction time. case "now": fact.Value.Domain = "" fact.Value.Name = tx.StartTime.String() // Set the value to the transaction entity. case "tx": fact.Value.Domain = origins.TransactionsDomain fact.Value.Name = fmt.Sprint(tx.ID) default: return fmt.Errorf("transactor(%s): unknown value macro: %s", tx.ID, fact.Value.Name) } } return nil }