1use crate::{
2 hdk,
3 hdk_extensions,
4};
5
6use hdk::prelude::*;
7use hdk_extensions::{
8 agent_id,
9};
10
11
12pub struct LinkBase<LT>(pub AnyLinkableHash, pub LT)
13where
14 LT: LinkTypeFilterExt + Copy,
15 ScopedLinkType: TryFrom<LT, Error = WasmError>,
16;
17
18
19impl<LT,T> TryFrom<(T, LT)> for LinkBase<LT>
20where
21 LT: LinkTypeFilterExt + Copy,
22 ScopedLinkType: TryFrom<LT, Error = WasmError>,
23 AnyLinkableHash: TryFrom<T, Error = WasmError>,
24{
25 type Error = WasmError;
26
27 fn try_from(input: (T, LT)) -> ExternResult<Self> {
28 Ok(
29 Self( AnyLinkableHash::try_from(input.0)?, input.1 )
30 )
31 }
32}
33
34
35impl<LT> LinkBase<LT>
36where
37 LT: LinkTypeFilterExt + Copy,
38 ScopedLinkType: TryFrom<LT, Error = WasmError>,
39{
40 pub fn new<T>(input: T, link_type: LT) -> Self
41 where
42 T: Into<AnyLinkableHash>,
43 {
44 Self( input.into(), link_type )
45 }
46
47 pub fn hash(&self) -> AnyLinkableHash {
48 self.0.clone()
49 }
50
51 pub fn link_type(&self) -> LT {
52 self.1
53 }
54
55 pub fn get_links(&self, tag: Option<LinkTag>) ->
56 ExternResult<Vec<Link>>
57 {
58 get_links( self.hash(), self.link_type(), tag )
59 }
60
61 pub fn create_link<T>(
62 &self,
63 target: &T,
64 tag: impl Into<LinkTag>
65 ) -> ExternResult<ActionHash>
66 where
67 T: Into<AnyLinkableHash> + Clone,
68 {
69 create_link( self.hash(), target.to_owned(), self.link_type(), tag )
70 }
71
72 pub fn links_exist<T>(&self, target: &T, tag: impl Into<LinkTag>) ->
73 ExternResult<Option<Link>>
74 where
75 T: Into<AnyLinkableHash> + Clone,
76 {
77 let tag : LinkTag = tag.into();
78
79 Ok(
80 self.get_links( Some(tag.clone()) )?.into_iter()
81 .find( |link| {
82 link.target == target.to_owned().into()
83 && link.tag == tag
84 })
85 )
86 }
87
88 pub fn create_link_if_not_exists<T>(
89 &self,
90 target: &T,
91 tag: impl Into<LinkTag>
92 ) -> ExternResult<Option<ActionHash>>
93 where
94 T: Into<AnyLinkableHash> + Clone,
95 {
96 let target : AnyLinkableHash = target.to_owned().into();
97 let tag : LinkTag = tag.into();
98
99 for link in self.get_links( Some(tag.clone()) )? {
100 if link.target == target
103 && link.tag == tag
104 {
105 debug!("Target ({}) already exists for anchor {}", target, self.hash() );
106 return Ok( None );
107 }
108 }
109
110 Ok( Some( self.create_link( &target, tag )? ) )
111 }
112
113 pub fn delete_all_my_links_to_target<T>(
114 &self,
115 target: &T,
116 tag: Option<LinkTag>,
117 ) -> ExternResult<Vec<ActionHash>>
118 where
119 T: Into<AnyLinkableHash> + Clone,
120 {
121 let agent_id = agent_id()?;
122 let target : AnyLinkableHash = target.to_owned().into();
123 let mut deleted_links = vec![];
124
125 for link in self.get_links( tag.clone() )? {
126 if link.target == target
127 && ( tag == None
128 || Some(link.tag) == tag )
129 && link.author == agent_id
130 {
131 debug!("Deleting link ({}): {} => {}", link.create_link_hash, self.hash(), target );
132 let delete_action = delete_link( link.create_link_hash )?;
133 deleted_links.push( delete_action );
134 }
135 }
136
137 Ok( deleted_links )
138 }
139}