blob: 86656e9bc46d4c68113c124b0f62e71e68645000 [file] [log] [blame]
Bharat saraswal870c56f2016-02-20 21:57:16 +05301/*
2 * Copyright 2016 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.yangutils.translator.tojava;
18
19import java.io.File;
20import java.io.IOException;
21import java.util.LinkedList;
22import java.util.List;
23import java.util.SortedSet;
24import java.util.TreeSet;
25
26import org.onosproject.yangutils.datamodel.YangType;
27import org.onosproject.yangutils.translator.CachedFileHandle;
28import org.onosproject.yangutils.translator.GeneratedFileType;
29import org.onosproject.yangutils.translator.tojava.utils.JavaCodeSnippetGen;
30import org.onosproject.yangutils.translator.tojava.utils.JavaIdentifierSyntax;
31import org.onosproject.yangutils.translator.tojava.utils.MethodsGenerator;
32import org.onosproject.yangutils.utils.UtilConstants;
33import org.onosproject.yangutils.utils.io.impl.FileSystemUtil;
34import org.onosproject.yangutils.utils.io.impl.JavaDocGen;
35import org.onosproject.yangutils.utils.io.impl.SerializedDataStore;
36import org.onosproject.yangutils.utils.io.impl.JavaDocGen.JavaDocType;
37import org.onosproject.yangutils.utils.io.impl.CopyrightHeader;
38
39import static org.slf4j.LoggerFactory.getLogger;
40import org.slf4j.Logger;
41
42/**
43 * Maintain the information about the java file to be generated.
44 */
45public class CachedJavaFileHandle implements CachedFileHandle {
46
47 private static final Logger log = getLogger(CachedJavaFileHandle.class);
48
49 private static final int MAX_CACHABLE_ATTR = 64;
50 private static final String JAVA_FILE_EXTENSION = ".java";
51 private static final String TEMP_FILE_EXTENSION = ".tmp";
52
53 /**
54 * The type(s) of java source file(s) to be generated when the cached file
55 * handle is closed.
56 */
57 private GeneratedFileType genFileTypes;
58
59 /**
60 * The type(s) of java method to be generated when the cached file handle is
61 * closed.
62 */
63 private GeneratedMethodTypes genMethodTypes;
64
65 /**
66 * Java package in which the class/interface needs to be generated.
67 */
68 private String pkg;
69
70 /**
71 * Name of the object in YANG file.
72 */
73 private String yangName;
74
75 /**
76 * Sorted set of import info, to be used to maintain the set of classes to
77 * be imported in the generated class.
78 */
79 private SortedSet<ImportInfo> importSet;
80
81 /**
82 * Cached list of attribute info.
83 */
84 private List<AttributeInfo> attributeList;
85
86 /**
87 * Prevent invoking default constructor.
88 */
89 private CachedJavaFileHandle() {
90 setCachedAttributeList(new LinkedList<AttributeInfo>());
91 }
92
93 /**
94 * Create a cached file handle which takes care of adding attributes to the
95 * generated java file.
96 *
97 * @param pcg package in which class/interface need to be generated.
98 * @param yangName name of the attribute in YANG file.
99 * @param types the types of files that needs to be generated.
100 * @throws IOException file IO exception.
101 */
102 public CachedJavaFileHandle(String pcg, String yangName, GeneratedFileType types) throws IOException {
103 if ((new File(pcg).exists())) {
104 setGeneratedFileTypes(types);
105 setPackage(pcg);
106 setYangName(yangName);
107 } else {
108 FileSystemUtil.createPackage(pcg, yangName);
109 setGeneratedFileTypes(types);
110 setPackage(pcg);
111 setYangName(yangName);
112 }
113 }
114
115 /**
116 * Get the types of files being generated corresponding to the YANG
117 * definition.
118 *
119 * @return the types of files being generated corresponding to the YANG
120 * definition.
121 */
122 public GeneratedFileType getGeneratedFileTypes() {
123 return genFileTypes;
124 }
125
126 /**
127 * Set the types of files being generated corresponding to the YANG
128 * definition.
129 *
130 * @param fileTypes the types of files being generated corresponding to the
131 * YANG definition.
132 */
133 public void setGeneratedFileTypes(GeneratedFileType fileTypes) {
134 genFileTypes = fileTypes;
135 }
136
137 /**
138 * Get the corresponding name defined in YANG.
139 *
140 * @return the corresponding name defined in YANG.
141 */
142 public String getYangName() {
143 return yangName;
144 }
145
146 /**
147 * Set the corresponding name defined in YANG.
148 *
149 * @param yangName the corresponding name defined in YANG.
150 */
151 public void setYangName(String yangName) {
152 this.yangName = yangName;
153 }
154
155 /**
156 * Get the java package.
157 *
158 * @return the java package.
159 */
160 public String getPackage() {
161 return pkg;
162 }
163
164 /**
165 * Set the java package.
166 *
167 * @param pcg the package to set
168 */
169 public void setPackage(String pcg) {
170 pkg = pcg;
171 }
172
173 /**
174 * Get the set containing the imported class/interface info.
175 *
176 * @return the set containing the imported class/interface info.
177 */
178 public SortedSet<ImportInfo> getImportSet() {
179 return importSet;
180 }
181
182 /**
183 * Assign the set containing the imported class/interface info.
184 *
185 * @param importSet the set containing the imported class/interface info.
186 */
187 private void setImportSet(SortedSet<ImportInfo> importSet) {
188 this.importSet = importSet;
189 }
190
191 /**
192 * Add an imported class/interface info is it is not already part of the
193 * set. If already part of the set, return false, else add to set and return
194 * true.
195 *
196 * @param importInfo class/interface info being imported.
197 * @return status of new addition of class/interface to the import set
198 */
199 public boolean addImportInfo(ImportInfo importInfo) {
200 /*
201 * implement the import info adding. The return value will be used to
202 * check if the qualified name will be used or class/interface name will
203 * be used in the generated class.
204 */
205 if (getImportSet() == null) {
206 setImportSet(new TreeSet<ImportInfo>());
207 }
208 return getImportSet().add(importInfo);
209 }
210
211 /**
212 * Get the list of cached attribute list.
213 *
214 * @return the set containing the imported class/interface info.
215 */
216 public List<AttributeInfo> getCachedAttributeList() {
217 return attributeList;
218 }
219
220 /**
221 * Set the cached attribute list.
222 *
223 * @param attrList attribute list.
224 */
225 private void setCachedAttributeList(List<AttributeInfo> attrList) {
226 attributeList = attrList;
227 }
228
229 /**
230 * Flush the cached attribute list to the serialized file.
231 */
232 private void flushCacheAttrToSerFile() {
233
234 for (AttributeInfo attr : getCachedAttributeList()) {
235 parseAttributeInfo(attr);
236 }
237
238 /*
239 * clear the contents from the cached attribute list.
240 */
241 getCachedAttributeList().clear();
242 }
243
244 /**
245 * Add a new attribute to the file(s).
246 *
247 * @param attrType data type of the added attribute.
248 * @param name name of the attribute.
249 * @param isListAttr if the current added attribute needs to be maintained
250 * in a list.
251 */
252 @Override
253 public void addAttributeInfo(YangType<?> attrType, String name, boolean isListAttr) {
254
255 AttributeInfo newAttr = new AttributeInfo();
256 attrType.setDataTypeName(attrType.getDataTypeName().replace("\"", ""));
257 if (attrType.getDataTypeName().equals("string")) {
258 attrType.setDataTypeName(
259 attrType.getDataTypeName().substring(0, 1).toUpperCase() + attrType.getDataTypeName().substring(1));
260 }
261 newAttr.setAttributeType(attrType);
262 newAttr.setAttributeName(name);
263 newAttr.setListAttr(isListAttr);
264
265 /*
266 * TODO: get the prefix and name of data type from attrType and
267 * initialize in importInfo.
268 */
269
270 /**
271 * TODO: Handle QualifiedFlag for imports.
272 */
273
274 if (getCachedAttributeList() != null) {
275 if (getCachedAttributeList().size() == MAX_CACHABLE_ATTR) {
276 flushCacheAttrToSerFile();
277 }
278 getCachedAttributeList().add(newAttr);
279 } else {
280 List<AttributeInfo> newAttributeInfo = new LinkedList<>();
281 newAttributeInfo.add(newAttr);
282 setCachedAttributeList(newAttributeInfo);
283 }
284 name = JavaIdentifierSyntax.getCamelCase(name);
285 }
286
287 /**
288 * Flushes the cached contents to the target file, frees used resources.
289 */
290 @Override
291 public void close() throws IOException {
292
293 String className = getYangName();
294 className = (className.substring(0, 1).toUpperCase() + className.substring(1));
295 String packagePath = getPackage();
296 String filePath = UtilConstants.YANG_GEN_DIR + packagePath.replace(".", "/");
297 GeneratedFileType fileType = getGeneratedFileTypes();
298
299 /**
300 * Create interface file.
301 */
302 String interfaceFileName = className + JAVA_FILE_EXTENSION;
303 File interfaceFile = new File(filePath + File.separator + interfaceFileName);
304
305 /**
306 * Create temp builder interface file.
307 */
308 String builderInterfaceFileName = interfaceFileName + TEMP_FILE_EXTENSION;
309 File builderInterfaceFile = new File(filePath + File.separator + builderInterfaceFileName);
310
311 /**
312 * Create builder class file.
313 */
314 String builderFileName = className + UtilConstants.BUILDER + JAVA_FILE_EXTENSION;
315 File builderFile = new File(filePath + File.separator + builderFileName);
316 MethodsGenerator.setBuilderClassName(className + UtilConstants.BUILDER);
317
318 /**
319 * Create temp impl class file.
320 */
321
322 String implFileName = className + UtilConstants.IMPL + TEMP_FILE_EXTENSION;
323 File implTempFile = new File(filePath + File.separator + implFileName);
324
325 if (fileType.equals(GeneratedFileType.INTERFACE) || fileType.equals(GeneratedFileType.ALL)) {
326
327 try {
328 interfaceFile.createNewFile();
329 appendContents(interfaceFile, className, GeneratedFileType.INTERFACE);
330 } catch (IOException e) {
331 throw new IOException("Failed to create interface file.");
332 }
333 }
334
335 if (fileType.equals(GeneratedFileType.BUILDER_CLASS) || fileType.equals(GeneratedFileType.ALL)) {
336
337 try {
338 builderFile.createNewFile();
339 appendContents(builderFile, className, GeneratedFileType.BUILDER_CLASS);
340 } catch (IOException e) {
341 throw new IOException("Failed to create builder class file.");
342 }
343 }
344
345 if (fileType.equals(GeneratedFileType.IMPL) || fileType.equals(GeneratedFileType.ALL)) {
346
347 try {
348 implTempFile.createNewFile();
349 appendContents(implTempFile, className, GeneratedFileType.IMPL);
350 } catch (IOException e) {
351 throw new IOException("Failed to create impl class file.");
352 }
353 }
354
355 if (fileType.equals(GeneratedFileType.BUILDER_INTERFACE) || fileType.equals(GeneratedFileType.ALL)) {
356
357 try {
358 builderInterfaceFile.createNewFile();
359 appendContents(builderInterfaceFile, className, GeneratedFileType.BUILDER_INTERFACE);
360 } catch (IOException e) {
361 throw new IOException("Failed to create builder interface class file.");
362 }
363 }
364 /*
365 * TODO: add the file header using
366 * JavaCodeSnippetGen.getFileHeaderComment
367 */
368 /*
369 * TODO: get the import list using getImportText and add to the
370 * generated java file using JavaCodeSnippetGen.getImportText
371 */
372
373 List<String> attributes = new LinkedList<>();
374 List<String> interfaceMethods = new LinkedList<>();
375 List<String> builderInterfaceMethods = new LinkedList<>();
376 List<String> builderClassMethods = new LinkedList<>();
377 List<String> implClassMethods = new LinkedList<>();
378 //TODO: Handle imports for the attributes.
379 try {
380 attributes = SerializedDataStore.getSerializeData(SerializedDataStore.SerializedDataStoreType.ATTRIBUTE);
381
382 interfaceMethods = SerializedDataStore
383 .getSerializeData(SerializedDataStore.SerializedDataStoreType.INTERFACE_METHODS);
384
385 builderInterfaceMethods = SerializedDataStore
386 .getSerializeData(SerializedDataStore.SerializedDataStoreType.BUILDER_INTERFACE_METHODS);
387
388 builderClassMethods = SerializedDataStore
389 .getSerializeData(SerializedDataStore.SerializedDataStoreType.BUILDER_METHODS);
390
391 implClassMethods = SerializedDataStore
392 .getSerializeData(SerializedDataStore.SerializedDataStoreType.IMPL_METHODS);
393
394 //TODO:imports = SerializedDataStore.getSerializeData(SerializedDataStore.SerializedDataStoreType.IMPORT);
395 } catch (ClassNotFoundException | IOException e) {
396 log.info("There is no attribute info of " + className + " YANG file in the serialized files.");
397 }
398
399 if (getCachedAttributeList() != null) {
400 MethodsGenerator.setAttrInfo(getCachedAttributeList());
401 for (AttributeInfo attr : getCachedAttributeList()) {
402 attributes.add(getAttributeString(attr));
403
404 interfaceMethods.add(MethodsGenerator.getMethodString(attr, GeneratedFileType.INTERFACE));
405
406 builderClassMethods.add(MethodsGenerator.getMethodString(attr, GeneratedFileType.BUILDER_CLASS));
407
408 builderInterfaceMethods
409 .add(MethodsGenerator.getMethodString(attr, GeneratedFileType.BUILDER_INTERFACE));
410
411 implClassMethods.add(MethodsGenerator.getMethodString(attr, GeneratedFileType.IMPL));
412 }
413 }
414
415 builderInterfaceMethods.add(MethodsGenerator.parseBuilderInterfaceBuildMethodString(className));
416 builderClassMethods.add(UtilConstants.FOUR_SPACE_INDENTATION + UtilConstants.JAVA_DOC_FIRST_LINE
417 + MethodsGenerator.getDefaultConstructorString(GeneratedFileType.BUILDER_CLASS, className));
418 builderClassMethods.add(MethodsGenerator.getBuildString(className));
419
420 implClassMethods.add(UtilConstants.JAVA_DOC_FIRST_LINE
421 + MethodsGenerator.getDefaultConstructorString(GeneratedFileType.IMPL, className));
422 implClassMethods.add(MethodsGenerator.getConstructorString(className));
423
424 /**
425 * Add attributes to the file.
426 */
427 for (String attribute : attributes) {
428 insert(builderFile, UtilConstants.NEW_LINE + UtilConstants.FOUR_SPACE_INDENTATION + attribute);
429 insert(implTempFile, UtilConstants.NEW_LINE + UtilConstants.FOUR_SPACE_INDENTATION + attribute);
430 }
431
432 insert(builderFile, UtilConstants.NEW_LINE);
433 insert(implTempFile, UtilConstants.NEW_LINE);
434
435 /**
436 * Add getter methods to interface file.
437 */
438 for (String method : interfaceMethods) {
439 appendMethod(interfaceFile, method + UtilConstants.NEW_LINE);
440 }
441
442 /**
443 * Add getters and setters in builder interface.
444 */
445 for (String method : builderInterfaceMethods) {
446 appendMethod(builderInterfaceFile, UtilConstants.FOUR_SPACE_INDENTATION + method + UtilConstants.NEW_LINE);
447 }
448
449 insert(builderInterfaceFile, UtilConstants.CLOSE_CURLY_BRACKET + UtilConstants.NEW_LINE);
450 /**
451 * Add methods in builder class.
452 */
453 for (String method : builderClassMethods) {
454 appendMethod(builderFile, method + UtilConstants.NEW_LINE);
455 }
456
457 /**
458 * Add methods in impl class.
459 */
460 for (String method : implClassMethods) {
461 appendMethod(implTempFile, UtilConstants.FOUR_SPACE_INDENTATION + method + UtilConstants.NEW_LINE);
462 }
463
464 insert(implTempFile, UtilConstants.CLOSE_CURLY_BRACKET + UtilConstants.NEW_LINE);
465
466 /**
467 * Append builder interface file to interface file and close it.
468 */
469 appendFileContents(builderInterfaceFile, interfaceFile);
470 insert(interfaceFile, closeFile(GeneratedFileType.INTERFACE, interfaceFileName));
471
472 /**
473 * Append impl class to builder class and close it.
474 */
475 appendFileContents(implTempFile, builderFile);
476 insert(builderFile, closeFile(GeneratedFileType.BUILDER_CLASS, builderFileName));
477
478 /**
479 * Remove temp files.
480 */
481 clean(implTempFile);
482 clean(builderInterfaceFile);
483 }
484
485 /**
486 * Appends the temp files to main files.
487 *
488 * @param appendFile temp file
489 * @param srcFile main file
490 */
491 private static void appendFileContents(File appendFile, File srcFile) throws IOException {
492 try {
493 FileSystemUtil.appendFileContents(appendFile, srcFile);
494 } catch (IOException e) {
495 throw new IOException("Failed to append " + appendFile + " in " + srcFile);
496 }
497 }
498
499 /**
500 * Append methods to the generated files.
501 *
502 * @param file file in which method needs to be appended.
503 * @param method method which needs to be appended.
504 */
505 private static void appendMethod(File file, String method) throws IOException {
506 insert(file, method);
507 }
508
509 /**
510 * Closes the current generated file.
511 *
512 * @param fileType generate file type
513 * @param yangName file name
514 * @return end of class definition string.
515 */
516 private static String closeFile(GeneratedFileType fileType, String yangName) {
517 return JavaCodeSnippetGen.getJavaClassDefClose(fileType, yangName);
518 }
519
520 /**
521 * Parses attribute info and fetch specific data and creates serialized
522 * files of it.
523 *
524 * @param attr attribute info.
525 */
526 private void parseAttributeInfo(AttributeInfo attr) {
527
528 String attrString = "";
529 String methodString = "";
530 String getterString = "";
531
532 try {
533 /*
534 * Serialize attributes.
535 */
536 attrString = getAttributeString(attr);
537 attrString = attrString.replace("\"", "");
538 SerializedDataStore.setSerializeData(attrString, SerializedDataStore.SerializedDataStoreType.ATTRIBUTE);
539
540 if (getGeneratedFileTypes().equals(GeneratedFileType.ALL)) {
541
542 methodString = MethodsGenerator.getMethodString(attr, GeneratedFileType.INTERFACE);
543 SerializedDataStore.setSerializeData(methodString,
544 SerializedDataStore.SerializedDataStoreType.INTERFACE_METHODS);
545
546 methodString = MethodsGenerator.getMethodString(attr, GeneratedFileType.BUILDER_CLASS);
547 SerializedDataStore.setSerializeData(methodString,
548 SerializedDataStore.SerializedDataStoreType.BUILDER_METHODS);
549
550 methodString = MethodsGenerator.getMethodString(attr, GeneratedFileType.BUILDER_INTERFACE);
551 SerializedDataStore.setSerializeData(methodString,
552 SerializedDataStore.SerializedDataStoreType.BUILDER_INTERFACE_METHODS);
553
554 methodString = MethodsGenerator.getMethodString(attr, GeneratedFileType.IMPL);
555 SerializedDataStore.setSerializeData(methodString,
556 SerializedDataStore.SerializedDataStoreType.IMPL_METHODS);
557
558 } else if (getGeneratedFileTypes().equals(GeneratedFileType.INTERFACE)) {
559
560 getterString = MethodsGenerator.getGetterString(attr);
561 SerializedDataStore.setSerializeData(methodString,
562 SerializedDataStore.SerializedDataStoreType.INTERFACE_METHODS);
563 }
564 } catch (IOException e) {
565 log.info("Failed to get data for " + attr.getAttributeName() + " from serialized files.");
566 }
567 }
568
569 /**
570 * Returns attribute string.
571 *
572 * @param attr attribute info
573 * @return attribute string
574 */
575 private String getAttributeString(AttributeInfo attr) {
576 return JavaCodeSnippetGen.getJavaAttributeInfo(getGeneratedFileTypes(), attr.getAttributeName(),
577 attr.getAttributeType());
578 }
579
580 /**
581 * Appends all the contents into a generated java file.
582 *
583 * @param file generated file
584 * @param fileName generated file name
585 * @param type generated file type
586 */
587 private void appendContents(File file, String fileName, GeneratedFileType type) throws IOException {
588
589 if (type.equals(GeneratedFileType.IMPL)) {
590
591 write(file, fileName, type, JavaDocType.IMPL_CLASS);
592 } else if (type.equals(GeneratedFileType.BUILDER_INTERFACE)) {
593
594 write(file, fileName, type, JavaDocType.BUILDER_INTERFACE);
595 } else {
596
597 // TODO: handle imports for attributes.
598
599 if (type.equals(GeneratedFileType.INTERFACE)) {
600 insert(file, CopyrightHeader.getCopyrightHeader());
601 insert(file, "package" + UtilConstants.SPACE + getPackage() + UtilConstants.SEMI_COLAN
602 + UtilConstants.NEW_LINE);
603 write(file, fileName, type, JavaDocType.INTERFACE);
604 } else if (type.equals(GeneratedFileType.BUILDER_CLASS)) {
605 insert(file, CopyrightHeader.getCopyrightHeader());
606 insert(file, "package" + UtilConstants.SPACE + getPackage() + UtilConstants.SEMI_COLAN
607 + UtilConstants.NEW_LINE);
608 write(file, fileName, type, JavaDocType.BUILDER_CLASS);
609 }
610 }
611 }
612
613 /**
614 * Write data to the specific generated file.
615 *
616 * @param file generated file
617 * @param fileName file name
618 * @param genType generated file type
619 * @param javaDocType java doc type
620 */
621 private static void write(File file, String fileName, GeneratedFileType genType, JavaDocGen.JavaDocType javaDocType)
622 throws IOException {
623
624 insert(file, JavaDocGen.getJavaDoc(javaDocType, fileName));
625 insert(file, JavaCodeSnippetGen.getJavaClassDefStart(genType, fileName));
626 }
627
628 /**
629 * Insert in the generated file.
630 *
631 * @param file file in which need to be inserted.
632 * @param data data which need to be inserted.
633 */
634 private static void insert(File file, String data) throws IOException {
635 try {
636 FileSystemUtil.insertStringInFile(file, data);
637 } catch (IOException e) {
638 throw new IOException("Failed to insert in " + file + "file");
639 }
640 }
641
642 /**
643 * Removes temp files.
644 *
645 * @param file file to be removed.
646 */
647 private static void clean(File file) {
648 if (file.exists()) {
649 file.delete();
650 }
651 }
652}