github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/base/component/component.go (about) 1 package component 2 3 import ( 4 "fmt" 5 "time" 6 7 "github.com/qri-io/dataset" 8 "github.com/qri-io/qfs" 9 ) 10 11 // Component represents one of two things, either a single component (meta, body), or a collection 12 // of components, such as an entire dataset or a directory of files that encode components. 13 type Component interface { 14 Base() *BaseComponent 15 Compare(Component) (bool, error) 16 WriteTo(dirPath string) (targetFile string, err error) 17 RemoveFrom(dirPath string) error 18 DropDerivedValues() 19 LoadAndFill(*dataset.Dataset) error 20 StructuredData() (interface{}, error) 21 } 22 23 // NumberPossibleComponents is the number of subcomponents plus "dataset". 24 const NumberPossibleComponents = 8 25 26 // AllSubcomponentNames is the names of subcomponents that can live on a collection. 27 func AllSubcomponentNames() []string { 28 return []string{"commit", "meta", "structure", "readme", "viz", "transform", "body"} 29 } 30 31 // ConvertDatasetToComponents will convert a dataset to a component collection 32 func ConvertDatasetToComponents(ds *dataset.Dataset, qfilesys qfs.Filesystem) Component { 33 dc := DatasetComponent{} 34 dc.Value = ds 35 dc.Subcomponents = make(map[string]Component) 36 37 dc.Subcomponents["dataset"] = &dc 38 if ds.Meta != nil { 39 mc := MetaComponent{} 40 mc.Value = ds.Meta 41 dc.Subcomponents["meta"] = &mc 42 } 43 if ds.Structure != nil { 44 sc := StructureComponent{} 45 sc.Value = ds.Structure 46 dc.Subcomponents["structure"] = &sc 47 } 48 if ds.Commit != nil { 49 cc := CommitComponent{} 50 cc.Value = ds.Commit 51 dc.Subcomponents["commit"] = &cc 52 } 53 if ds.Readme != nil { 54 rc := ReadmeComponent{Resolver: qfilesys} 55 rc.Value = ds.Readme 56 rc.Format = "md" 57 dc.Subcomponents["readme"] = &rc 58 } 59 if ds.Transform != nil { 60 dc.Subcomponents["transform"] = &TransformComponent{ 61 BaseComponent: BaseComponent{Format: "star"}, 62 Resolver: qfilesys, 63 Value: ds.Transform, 64 } 65 } 66 67 if ds.Body != nil { 68 bc := BodyComponent{Resolver: qfilesys} 69 bc.Value = ds.Body 70 bc.BodyFile = ds.BodyFile() 71 bc.Structure = ds.Structure 72 if ds.Structure != nil { 73 bc.Format = ds.Structure.Format 74 } 75 dc.Subcomponents["body"] = &bc 76 } else if ds.BodyPath != "" { 77 bc := BodyComponent{Resolver: qfilesys} 78 bc.SourceFile = ds.BodyPath 79 bc.BodyFile = ds.BodyFile() 80 bc.Structure = ds.Structure 81 if ds.Structure != nil { 82 bc.Format = ds.Structure.Format 83 } 84 dc.Subcomponents["body"] = &bc 85 } 86 87 return &dc 88 } 89 90 // ToDataset converts a component to a dataset. Should only be used on a 91 // component representing an entire dataset. 92 func ToDataset(comp Component) (*dataset.Dataset, error) { 93 dsComp := comp.Base().GetSubcomponent("dataset") 94 if dsComp == nil { 95 comp := DatasetComponent{} 96 comp.Value = &dataset.Dataset{} 97 dsComp = &comp 98 } 99 dsCont, ok := dsComp.(*DatasetComponent) 100 if !ok { 101 return nil, fmt.Errorf("could not cast component to a Dataset") 102 } 103 ds := dsCont.Value 104 if mdComponent := comp.Base().GetSubcomponent("meta"); mdComponent != nil { 105 if err := mdComponent.LoadAndFill(ds); err != nil { 106 return nil, err 107 } 108 } 109 if cmComponent := comp.Base().GetSubcomponent("commit"); cmComponent != nil { 110 if err := cmComponent.LoadAndFill(ds); err != nil { 111 return nil, err 112 } 113 } 114 if stComponent := comp.Base().GetSubcomponent("structure"); stComponent != nil { 115 if err := stComponent.LoadAndFill(ds); err != nil { 116 return nil, err 117 } 118 } 119 if rmComponent := comp.Base().GetSubcomponent("readme"); rmComponent != nil { 120 if err := rmComponent.LoadAndFill(ds); err != nil { 121 return nil, err 122 } 123 } 124 if tfComponent := comp.Base().GetSubcomponent("transform"); tfComponent != nil { 125 if err := tfComponent.LoadAndFill(ds); err != nil { 126 return nil, err 127 } 128 } 129 if bdComponent := comp.Base().GetSubcomponent("body"); bdComponent != nil { 130 if !bdComponent.Base().IsLoaded { 131 ds.BodyPath = bdComponent.Base().SourceFile 132 } 133 } 134 return ds, nil 135 } 136 137 // BaseComponent is the data elements common to any component 138 type BaseComponent struct { 139 Subcomponents map[string]Component 140 ProblemKind string 141 ProblemMessage string 142 // File information: 143 ModTime time.Time 144 SourceFile string 145 IsLoaded bool 146 Format string 147 }