Пример #1
0
// 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()
}
Пример #2
0
// 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
}
Пример #3
0
// 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
}
Пример #4
0
// 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
}