1+ @file:Suppress(" unused" )
2+
13package com.dengzii.plugin.template.model
24
35import com.dengzii.plugin.template.template.Placeholder
@@ -16,14 +18,21 @@ import java.util.*
1618</pre> */
1719open class FileTreeNode private constructor() {
1820
21+ // the backing field is 'realName'
1922 var name: String
2023 get() = realName.replacePlaceholder(placeHolderMap)
2124 set(value) {
2225 realName = value
2326 }
2427
2528 var isDir = true
26- var children = mutableListOf<FileTreeNode >()
29+ var children
30+ set(value) {
31+ realChildren = value
32+ realChildren.forEach { labeledChildren[it.getLabel()] = it }
33+ }
34+ get() = realChildren
35+
2736 var placeHolderMap: MutableMap <String , String >? = null
2837 get() = field ? : parent?.placeHolderMap
2938
@@ -34,8 +43,11 @@ open class FileTreeNode private constructor() {
3443 var fileTemplates: MutableMap <String , String >? = null
3544 get() = field ? : parent?.fileTemplates
3645
46+ private var realChildren = mutableSetOf<FileTreeNode >()
3747 // the origin name with original placeholder
3848 private var realName: String = " "
49+ // the label composed by 'name' and 'isDir'.
50+ private val labeledChildren = mutableMapOf<String , FileTreeNode >()
3951 @Transient
4052 var parent: FileTreeNode ? = null
4153
@@ -72,12 +84,28 @@ open class FileTreeNode private constructor() {
7284
7385 fun removeFromParent (): Boolean {
7486 if (parent != null ) {
87+ parent!! .labeledChildren.remove(getLabel())
7588 parent!! .children.remove(this )
7689 return true
7790 }
7891 return false
7992 }
8093
94+ fun addChild (child : FileTreeNode , override : Boolean = false): Boolean {
95+ if (hasChild(child.getLabel())) {
96+ if (override ) {
97+ Logger .d(TAG , " node has already exists $child " )
98+ return false
99+ } else {
100+ Logger .d(TAG , " override node ${child.getPath()} " )
101+ }
102+ }
103+ child.parent = this
104+ children.add(child)
105+ labeledChildren[child.getLabel()] = child
106+ return true
107+ }
108+
81109 fun hasChild (name : String , isDir : Boolean ): Boolean {
82110 children.forEach {
83111 if (it.isDir == isDir && it.realName == name) {
@@ -87,6 +115,14 @@ open class FileTreeNode private constructor() {
87115 return false
88116 }
89117
118+ fun hasChild (label : String ): Boolean {
119+ return labeledChildren.containsKey(label)
120+ }
121+
122+ /* *
123+ * get the origin name without replace with placeholder
124+ * real name is the value when you set field 'name'
125+ */
90126 fun getRealName (): String {
91127 return realName
92128 }
@@ -98,19 +134,23 @@ open class FileTreeNode private constructor() {
98134 fileTemplates!! [fileName] = template
99135 }
100136
101- fun hasTemplate (): Boolean {
137+ fun hasFileTemplate (): Boolean {
102138 return template != null || fileTemplates?.containsKey(realName) == true
103139 }
104140
105141 fun getTemplateName (): String? {
106142 return template ? : fileTemplates?.get(realName)
107143 }
108144
109- fun placeholder (placeholder : Placeholder , value : String ) {
145+ fun placeholder (name : String , value : String ) {
110146 if (this .placeHolderMap == null ) {
111147 this .placeHolderMap = kotlin.collections.mutableMapOf ()
112148 }
113- placeHolderMap!! [placeholder.getPlaceholder()] = value
149+ placeHolderMap!! [name] = value
150+ }
151+
152+ fun placeholder (placeholder : Placeholder ) {
153+ placeholder(placeholder.placeholder, placeholder.value)
114154 }
115155
116156 /* *
@@ -153,43 +193,56 @@ open class FileTreeNode private constructor() {
153193 }
154194
155195 /* *
156- * merge all children of another node to ' this.children' .
196+ * merge all children of another node to this.
157197 */
158- fun include (other : FileTreeNode ) {
198+ fun include (other : FileTreeNode , override : Boolean = false ) {
159199 if (! isDir) return
160200 other.children.forEach {
161- val child = it.clone()
162- child.parent = this
163- children.add(child)
201+ addChild(it.clone(), override )
164202 }
165203 }
166204
205+ /* *
206+ * create directory nodes from the path
207+ *
208+ * @param path The dir path
209+ * @param block The child node domain
210+ */
167211 fun dir (path : String , block : FileTreeNode .() -> Unit = {}) {
168212 if (! isDir) return
169213 val dirs = path.split(" /" ).filter { it.isNotBlank() }.toMutableList()
170214 createDirs(dirs, this )(block)
171215 }
172216
217+ /* *
218+ * create directories tree from a list
219+ * the larger the index, the deeper the directory
220+ *
221+ * @param dirs The dirs list to create tree
222+ * @param parent The parent of current node
223+ */
173224 private fun createDirs (dirs : MutableList <String >, parent : FileTreeNode ): FileTreeNode {
174225 if (dirs.isEmpty()) {
175226 return parent
176227 }
177228 val current = dirs[0 ]
178229 dirs.removeAt(0 )
179230 val dirNode = FileTreeNode (parent, current, true )
180- parent.children.add (dirNode)
231+ addChild (dirNode)
181232 return createDirs(dirs, dirNode)
182233 }
183234
184235 fun file (name : String ) {
185236 if (! isDir) return
186- children.add (FileTreeNode (this , name, false ))
237+ addChild (FileTreeNode (this , name, false ))
187238 }
188239
189240 /* *
190241 * get path of current node.
191242 * if the current node is the root node, it will return absolute path,
192243 * otherwise return relative path.
244+ *
245+ * @return The intact path of current node
193246 */
194247 fun getPath (): String {
195248 if (isRoot() || parent == null || parent!! .name == " " ) {
@@ -206,16 +259,28 @@ open class FileTreeNode private constructor() {
206259 return getNodeGraph().toString()
207260 }
208261
262+ /* *
263+ * clone current node, the following fields will be copied:
264+ * name, isDir, fileTemplates, placeHolderMap, children
265+ *
266+ * the parent will not be cloned
267+ */
209268 fun clone (): FileTreeNode {
210- val cl = FileTreeNode (null , name, isDir)
211- cl .fileTemplates = fileTemplates?.toMutableMap()
212- cl .placeHolderMap = placeHolderMap?.toMutableMap()
269+ val clone = FileTreeNode (null , name, isDir)
270+ clone .fileTemplates = fileTemplates?.toMutableMap()
271+ clone .placeHolderMap = placeHolderMap?.toMutableMap()
213272 children.forEach {
214- val child = it.clone()
215- child.parent = cl
216- cl.children.add(child)
273+ clone.addChild(it.clone())
217274 }
218- return cl
275+ return clone
276+ }
277+
278+ private fun removeChild (label : String ): FileTreeNode ? {
279+ if (hasChild(label)) {
280+ children.remove(labeledChildren[label])
281+ return labeledChildren.remove(label)
282+ }
283+ return null
219284 }
220285
221286 private fun getNodeGraph (head : Stack <String > = Stack (), str : StringBuilder = StringBuilder ()): StringBuilder {
@@ -263,7 +328,11 @@ open class FileTreeNode private constructor() {
263328 }
264329 }
265330
331+ private fun getLabel (): String {
332+ return " name_$isDir "
333+ }
334+
266335 override fun toString (): String {
267- return " FileTreeNode(path='${getPath()} ')"
336+ return " FileTreeNode(path='${getPath()} ' isDir= $isDir )"
268337 }
269338}
0 commit comments