001 /**
002 * Copyright 2005-2013 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.krad.demo.uif.components;
017
018 import org.apache.commons.io.FileUtils;
019 import org.apache.commons.io.LineIterator;
020 import org.kuali.rice.core.api.util.AbstractKeyValue;
021 import org.kuali.rice.core.api.util.ConcreteKeyValue;
022 import org.kuali.rice.core.api.util.KeyValue;
023 import org.kuali.rice.krad.datadictionary.parse.BeanTag;
024 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
025 import org.kuali.rice.krad.datadictionary.parse.BeanTags;
026 import org.kuali.rice.krad.messages.MessageService;
027 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
028 import org.kuali.rice.krad.uif.component.Component;
029 import org.kuali.rice.krad.uif.container.Group;
030 import org.kuali.rice.krad.uif.container.TabGroup;
031 import org.kuali.rice.krad.uif.control.MultiValueControl;
032 import org.kuali.rice.krad.uif.element.Header;
033 import org.kuali.rice.krad.uif.element.Message;
034 import org.kuali.rice.krad.uif.field.InputField;
035 import org.kuali.rice.krad.uif.util.ComponentFactory;
036 import org.kuali.rice.krad.uif.view.FormView;
037 import org.kuali.rice.krad.uif.view.View;
038 import org.springframework.util.StringUtils;
039
040 import javax.swing.text.StyleContext;
041 import java.io.File;
042 import java.lang.reflect.Method;
043 import java.net.URL;
044 import java.util.ArrayList;
045 import java.util.Arrays;
046 import java.util.Collections;
047 import java.util.Comparator;
048 import java.util.HashMap;
049 import java.util.List;
050 import java.util.Map;
051 import java.util.regex.Matcher;
052 import java.util.regex.Pattern;
053
054 /**
055 * View for the ComponentLibrary demo examples of Uif Components
056 *
057 * @author Kuali Rice Team (rice.collab@kuali.org)
058 */
059 public class ComponentLibraryView extends FormView {
060 private static final long serialVersionUID = 3981186175467661843L;
061
062 private String rootJavadocAddress;
063 private String rootDocBookAddress;
064 private String docBookAnchor;
065 private String componentName;
066 private String javaFullClassPath;
067 private String xmlFilePath;
068 private String description;
069 private String usage;
070 private String largeExampleFieldId;
071
072 public static enum ExampleSize {
073 SMALL, LARGE, XLARGE, WINDOW;
074 }
075
076 private ExampleSize exampleSize;
077
078 private Group detailsGroup;
079
080 private ComponentExhibit exhibit;
081 private List<Group> demoGroups;
082
083 /**
084 * Initializes the TabGroup that contains description and usage. Processes ths source code marked with the
085 * ex: comment tags and adds them to the ComponentExhibit for this view.
086 *
087 * @see Component#performInitialization(org.kuali.rice.krad.uif.view.View, Object)
088 */
089 @Override
090 public void performInitialization(View view, Object model) {
091 super.performInitialization(view, model);
092
093 MessageService messageService = KRADServiceLocatorWeb.getMessageService();
094
095 //set page name
096 this.getPage().setHeaderText(this.getComponentName());
097
098 TabGroup tabGroup = ComponentFactory.getTabGroup();
099 List<Component> tabItems = new ArrayList<Component>();
100
101 //Description processing
102 Group descriptionGroup = ComponentFactory.getVerticalBoxGroup();
103
104 //Description header
105 Header descriptionHeader = (Header) ComponentFactory.getNewComponentInstance("Uif-SubSectionHeader");
106 descriptionHeader.setHeaderLevel("H3");
107 descriptionHeader.setHeaderText(messageService.getMessageText("KR-SAP", null, "componentLibrary.description"));
108 descriptionHeader.setRender(false);
109 descriptionGroup.setHeader(descriptionHeader);
110
111 //Description message
112 List<Component> descriptionItems = new ArrayList<Component>();
113 Message descriptionMessage = ComponentFactory.getMessage();
114 descriptionMessage.setMessageText(description);
115 descriptionItems.add(descriptionMessage);
116 descriptionGroup.setItems(descriptionItems);
117
118 tabItems.add(descriptionGroup);
119
120 //Usage processing
121 Group usageGroup = ComponentFactory.getVerticalBoxGroup();
122
123 //Usage header
124 Header usageHeader = (Header) ComponentFactory.getNewComponentInstance("Uif-SubSectionHeader");
125 usageHeader.setHeaderLevel("H3");
126 usageHeader.setHeaderText(messageService.getMessageText("KR-SAP", null, "componentLibrary.usage"));
127 usageHeader.setRender(false);
128 usageGroup.setHeader(usageHeader);
129
130 //Usage message
131 List<Component> usageItems = new ArrayList<Component>();
132 Message usageMessage = ComponentFactory.getMessage();
133 usageMessage.setMessageText(usage);
134 usageItems.add(usageMessage);
135 usageGroup.setItems(usageItems);
136
137 tabItems.add(usageGroup);
138
139 //Documentation processing
140 if (javaFullClassPath != null) {
141 processDocumentationTab(tabItems);
142 }
143
144 //set tabGroup items
145 tabGroup.setItems(tabItems);
146
147 tabGroup.addStyleClass("demo-componentDetailsTabs");
148
149 //Add tabGroup to detailsGroup
150 List<Component> detailsItems = new ArrayList<Component>();
151 detailsItems.addAll(detailsGroup.getItems());
152 detailsItems.add(tabGroup);
153 detailsGroup.setItems(detailsItems);
154 view.assignComponentIds(detailsGroup);
155
156 //exhibit setup
157 List<String> sourceCode = new ArrayList<String>();
158
159 //process source
160 processXmlSource(sourceCode);
161
162 //setup exhibit
163 exhibit.setDemoSourceCode(sourceCode);
164 exhibit.setDemoGroups(this.getDemoGroups());
165
166 if (this.getExampleSize() != null &&
167 (this.getExampleSize().equals(ExampleSize.LARGE) || this.getExampleSize().equals(ExampleSize.XLARGE))) {
168 exhibit.getTabGroup().addStyleClass("demo-noTabs");
169 Group headerRightGroup = view.getPage().getHeader().getRightGroup();
170 for (Component item : headerRightGroup.getItems()) {
171 if (item instanceof InputField && ((InputField) item).getControl() instanceof MultiValueControl && item
172 .getId().equals(this.getLargeExampleFieldId())) {
173 //List<ConcreteKeyValue> keyValues = new ArrayList<ConcreteKeyValue>();
174 List<KeyValue> values = new ArrayList<KeyValue>();
175 int i = 0;
176 for (Group demoGroup : demoGroups) {
177 values.add(new ConcreteKeyValue(demoGroup.getId(), demoGroup.getHeader().getHeaderText()));
178 i++;
179 }
180
181 //values.addAll(keyValues);
182 ((MultiValueControl) ((InputField) item).getControl()).setOptions(values);
183 item.setRender(true);
184 }
185 }
186 }
187
188 if(this.getExampleSize() != null && this.getExampleSize().equals(ExampleSize.XLARGE)){
189 this.addStyleClass("demo-xLargeLibraryView");
190 }
191
192 //Add detailsGroup and exhibit to page
193 List<Component> pageItems = new ArrayList<Component>();
194 pageItems.addAll(this.getPage().getItems());
195 pageItems.add(exhibit);
196 pageItems.add(detailsGroup);
197 this.getPage().setItems(pageItems);
198 }
199
200 /**
201 * Builds out the documentation tab content by auto-generating the content for properties and documentation and
202 * adds it to the tabItems list
203 *
204 * @param tabItems list of tab items for component details
205 */
206 private void processDocumentationTab(List<Component> tabItems) {
207 MessageService messageService = KRADServiceLocatorWeb.getMessageService();
208
209 try {
210 Class<?> componentClass = Class.forName(javaFullClassPath);
211 Method methodsArray[] = componentClass.getMethods();
212
213 //get top level documentation for this class
214 String classMessage = messageService.getMessageText("KR-SAP", null, javaFullClassPath);
215
216 if (classMessage == null) {
217 classMessage = "NO DOCUMENTATION AVAILABLE/FOUND... we are working on it!";
218 }
219
220 //scrub class message of @link and @code
221 classMessage = classMessage.replaceAll("\\{[@#]link (.*?)\\}", "<i>$1</i>");
222 classMessage = classMessage.replaceAll("\\{[@#]code (.*?)\\}", "<i>$1</i>");
223
224 //Generate schema and bean Id reference table
225 String schemaTable =
226 "<table class='demo-schemaIdDocTable'><tr><th>Schema Name</th>" + "<th>Uif Bean Id</th></tr>";
227 if (componentClass.isAnnotationPresent(BeanTag.class)) {
228 BeanTag beanTag = componentClass.getAnnotation(BeanTag.class);
229 schemaTable = schemaTable +
230 "<tr><td>" + beanTag.name() + "</td><td>" + beanTag.parent() + "</td></tr>";
231 schemaTable = schemaTable + "</table>";
232 } else if (componentClass.isAnnotationPresent(BeanTags.class)) {
233 BeanTags beanTags = componentClass.getAnnotation(BeanTags.class);
234 BeanTag[] beanTagArray = beanTags.value();
235 for (BeanTag beanTag : beanTagArray) {
236 schemaTable = schemaTable +
237 "<tr><td>" + beanTag.name() + "</td><td>" + beanTag.parent() + "</td></tr>";
238 }
239 schemaTable = schemaTable + "</table>";
240 } else {
241 schemaTable = "";
242 }
243
244 String javadocTitle = messageService.getMessageText("KR-SAP", null, "componentLibrary.javaDoc");
245 String kradGuideTitle = messageService.getMessageText("KR-SAP", null, "componentLibrary.kradGuide");
246 String devDocumentationTitle = messageService.getMessageText("KR-SAP", null,
247 "componentLibrary.devDocumentation");
248 String beanDefsTitle = messageService.getMessageText("KR-SAP", null, "componentLibrary.beanDefs");
249
250 //build documentation links from javadoc address and docbook address/anchor
251 String docLinkDiv = "<div class='demo-docLinks'> "
252 + "<label>Additional Resources:</label><a class='demo-documentationLink'"
253 + " href='"
254 + getRootJavadocAddress()
255 + javaFullClassPath.replace('.', '/')
256 + ".html' target='_blank'>"
257 + javadocTitle
258 + "</a>"
259 + "<a class='demo-documentationLink'"
260 + " href='"
261 + getRootDocBookAddress()
262 + getDocBookAnchor()
263 + "' target='_blank'>"
264 + kradGuideTitle
265 + "</a>"
266 + "</div>";
267
268 //initialize the documentation content
269 String documentationMessageContent =
270 "<H3>" + this.getComponentName() + " " + devDocumentationTitle + "</H3>" +
271 docLinkDiv + classMessage + "<H3>" + beanDefsTitle + "</H3>" + schemaTable;
272
273 List<String> propertyDescriptions = new ArrayList<String>();
274 Map<String, List<String>> inheritedProperties = new HashMap<String, List<String>>();
275
276 List<Method> methods = Arrays.asList(methodsArray);
277
278 //alphabetize the methods by name
279 Collections.sort(methods, new Comparator<Method>() {
280 @Override
281 public int compare(Method method1, Method method2) {
282 String name1 = getPropName(method1);
283 String name2 = getPropName(method2);
284 return name1.compareTo(
285 name2); //To change body of implemented methods use File | Settings | File Templates.
286 }
287 });
288
289 //Process all methods on this class
290 for (Method method : methods) {
291 BeanTagAttribute attribute = method.getAnnotation(BeanTagAttribute.class);
292 if (attribute != null) {
293 //property variables
294 String name = getPropName(method);
295 String methodClass = method.getDeclaringClass().getName();
296 String returnType = method.getReturnType().getName();
297 returnType = returnType.replaceAll("<.*?>", "");
298 String returnTypeShort = returnType.substring(returnType.lastIndexOf(".") + 1);
299
300 //get property documentation message
301 String key = methodClass + "|" + name + "|" + returnTypeShort;
302 String propertyMessage = messageService.getMessageText("KR-SAP", null, key);
303
304 if (propertyMessage == null) {
305 propertyMessage = "NO DOCUMENTATION AVAILABLE... we are working on it!";
306 }
307
308 //scrub property message of @link and @code
309 propertyMessage = propertyMessage.replaceAll("\\{[@#]link (.*?)\\}", "<i>$1</i>");
310 propertyMessage = propertyMessage.replaceAll("\\{[@#]code (.*?)\\}", "<i>$1</i>");
311
312 //wrap in link if a kuali type
313 if (returnType.startsWith("org.kuali")) {
314 returnTypeShort = "<a href='"
315 + getRootJavadocAddress()
316 + returnType.replace('.', '/')
317 + ".html' target='_blank'>"
318 + returnTypeShort
319 + "</a>";
320 }
321
322 //html propertyMessage content
323 propertyMessage = "<div class='demo-propertyItem'>"
324 + "<h4 class='demo-propertyName'>"
325 + name
326 + "</h4>"
327 + "<div class='demo-propertyType'>"
328 + returnTypeShort
329 + "</div>"
330 + "<div class='demo-propertyDesc'>"
331 + propertyMessage
332 + "</div></div>";
333
334 if (!methodClass.equals(javaFullClassPath)) {
335 //if this method comes from a parent and not this class, put it in the inheritedPropertiesMap
336 List<String> classProperties = inheritedProperties.get(methodClass);
337 if (classProperties == null) {
338 classProperties = new ArrayList<String>();
339 }
340 classProperties.add(propertyMessage);
341 inheritedProperties.put(methodClass, classProperties);
342 } else {
343 propertyDescriptions.add(propertyMessage);
344 }
345 }
346 }
347
348 documentationMessageContent =
349 documentationMessageContent + "<H3>Properties</H3><div class='demo-propertiesContent'>";
350 for (String desc : propertyDescriptions) {
351 documentationMessageContent = documentationMessageContent + desc;
352 }
353 documentationMessageContent = documentationMessageContent + "</div>";
354
355 Group documentationGroup = ComponentFactory.getVerticalBoxGroup();
356
357 //properties header
358 Header documentationHeader = (Header) ComponentFactory.getNewComponentInstance("Uif-SubSectionHeader");
359 documentationHeader.setHeaderLevel("H3");
360 documentationHeader.setHeaderText(messageService.getMessageText("KR-SAP", null,
361 "componentLibrary.documentation"));
362 documentationHeader.setRender(false);
363 documentationGroup.setHeader(documentationHeader);
364
365 List<Component> propertiesItems = new ArrayList<Component>();
366 Message propertiesMessage = ComponentFactory.getMessage();
367 propertiesMessage.setParseComponents(false);
368 propertiesMessage.setMessageText(documentationMessageContent);
369 propertiesItems.add(propertiesMessage);
370
371 //create the inherited properties disclosures
372 if (!inheritedProperties.isEmpty()) {
373
374 //todo sort alphabetically here?
375 for (String className : inheritedProperties.keySet()) {
376 String messageContent = "";
377 List<String> inheritedPropertyDescriptions = inheritedProperties.get(className);
378
379 for (String desc : inheritedPropertyDescriptions) {
380 messageContent = messageContent + desc;
381 }
382
383 Group iPropertiesGroup = ComponentFactory.getVerticalBoxGroup();
384
385 //inherited properties header
386 Header iPropHeader = (Header) ComponentFactory.getNewComponentInstance("Uif-SubSectionHeader");
387 iPropHeader.setHeaderLevel("H3");
388 iPropHeader.setHeaderText(messageService.getMessageText("KR-SAP", null,
389 "componentLibrary.inheritedFrom") + " " + className);
390 //iPropHeader.setRender(false);
391 iPropertiesGroup.setHeader(iPropHeader);
392 iPropertiesGroup.getDisclosure().setRender(true);
393 iPropertiesGroup.getDisclosure().setDefaultOpen(false);
394
395 List<Component> iPropertiesItems = new ArrayList<Component>();
396 Message iPropertiesMessage = ComponentFactory.getMessage();
397 iPropertiesMessage.setParseComponents(false);
398 iPropertiesMessage.setMessageText(messageContent);
399 iPropertiesItems.add(iPropertiesMessage);
400 iPropertiesGroup.setItems(iPropertiesItems);
401
402 propertiesItems.add(iPropertiesGroup);
403 }
404 }
405
406 documentationGroup.setItems(propertiesItems);
407
408 tabItems.add(documentationGroup);
409 } catch (Exception e) {
410 throw new RuntimeException("Error loading class: " + javaFullClassPath, e);
411 }
412 }
413
414 /**
415 * Gets the property name from the method by stripping get/is and making the first letter lowercase
416 *
417 * @param method the Method object
418 * @return the property name for the Method passed in
419 */
420 private String getPropName(Method method) {
421 String name = method.getName();
422
423 if (name.startsWith("get")) {
424 name = name.replaceFirst("get", "");
425 } else {
426 name = name.replaceFirst("is", "");
427 }
428
429 name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
430
431 return name;
432 }
433
434 /**
435 * Process xml source code to be consumed by the exhibit component
436 *
437 * @param sourceCode list of sourceCode to be filled in, in order the group exhibit examples appear
438 */
439 private void processXmlSource(List<String> sourceCode) {
440 Map<String, String> idSourceMap = new HashMap<String, String>();
441 if (xmlFilePath != null) {
442 try {
443 //Get the source file
444 URL fileUrl = ComponentLibraryView.class.getClassLoader().getResource(xmlFilePath);
445 File file = new File(fileUrl.toURI());
446 Pattern examplePattern = Pattern.compile("ex:(.*?)(\\s|(-->))");
447
448 boolean readingSource = false;
449 String currentSource = "";
450 String currentId = "";
451
452 LineIterator lineIt = FileUtils.lineIterator(file);
453 while (lineIt.hasNext()) {
454 String line = lineIt.next();
455 if (line.contains("ex:") && !readingSource) {
456 //found a ex: tag and are not already reading source
457 readingSource = true;
458
459 Matcher matcher = examplePattern.matcher(line);
460 if (matcher.find()) {
461 currentId = matcher.group(1);
462 }
463
464 currentSource = idSourceMap.get(currentId) != null ? idSourceMap.get(currentId) : "";
465
466 if (!currentSource.isEmpty()) {
467 currentSource = currentSource + "\n";
468 }
469 } else if (line.contains("ex:") && readingSource) {
470 //stop reading source on second ex tag
471 readingSource = false;
472 idSourceMap.put(currentId, currentSource);
473 } else if (readingSource) {
474 //when reading source just continue to add it
475 currentSource = currentSource + line + "\n";
476 }
477
478 }
479 } catch (Exception e) {
480 throw new RuntimeException(
481 "file not found or error while reading: " + xmlFilePath + " for source reading", e);
482 }
483 }
484
485 for (Group demoGroup : demoGroups) {
486 //add source to the source list by order that demo groups appear
487 String groupId = demoGroup.getId();
488 String source = idSourceMap.get(groupId);
489 if (source != null) {
490 //translate the source to something that can be displayed
491 sourceCode.add(translateSource(source));
492 }
493 }
494 }
495
496 /**
497 * Translates the source by removing chracters that the dom will misinterpret as html and to ensure
498 * source spacing is correct
499 *
500 * @param source the original source
501 * @return that translated source used in the SyntaxHighlighter of the exhibit
502 */
503 private String translateSource(String source) {
504 //convert characters to ascii equivalent
505 source = source.replace("<", "<");
506 source = source.replace(">", ">");
507 source = source.replaceAll("[ \\t]", " ");
508
509 Pattern linePattern = Pattern.compile("(( )*).*?(\\n)+");
510 Matcher matcher = linePattern.matcher(source);
511 int toRemove = -1;
512
513 //find the line with the least amount of spaces
514 while (matcher.find()) {
515 String spaces = matcher.group(1);
516
517 int count = StringUtils.countOccurrencesOf(spaces, " ");
518 if (toRemove == -1 || count < toRemove) {
519 toRemove = count;
520 }
521 }
522
523 matcher.reset();
524 String newSource = "";
525
526 //remove the min number of spaces from each line to get them to align left properly in the viewer
527 while (matcher.find()) {
528 String line = matcher.group();
529 newSource = newSource + line.replaceFirst("( ){" + toRemove + "}", "");
530 }
531
532 //remove very last newline
533 newSource = newSource.replaceAll("\\n$", "");
534 //replace remaining newlines with ascii equivalent
535 newSource = newSource.replace("\n", "
");
536
537 return newSource;
538 }
539
540 /**
541 * ComponentLibraryView constructor
542 */
543 public ComponentLibraryView() {
544 demoGroups = new ArrayList<Group>();
545 }
546
547 /**
548 * The name of the component (to be used by this page's header)
549 *
550 * @return componentName the name of the component being demoed
551 */
552 public String getComponentName() {
553 return componentName;
554 }
555
556 /**
557 * Sets the componentName
558 *
559 * @param componentName
560 */
561 public void setComponentName(String componentName) {
562 this.componentName = componentName;
563 }
564
565 /**
566 * Set the java path to the class being used by this component
567 * TODO not yet used
568 *
569 * @return the java path to the class
570 */
571 public String getJavaFullClassPath() {
572 return javaFullClassPath;
573 }
574
575 /**
576 * Get the java full class path
577 *
578 * @param javaFullClassPath
579 */
580 public void setJavaFullClassPath(String javaFullClassPath) {
581 this.javaFullClassPath = javaFullClassPath;
582 }
583
584 /**
585 * The xml file path that contains the source being used for this demo, must start with / (relative path)
586 *
587 * @return the xml file path
588 */
589 public String getXmlFilePath() {
590 return xmlFilePath;
591 }
592
593 /**
594 * Set the xml file path
595 *
596 * @param xmlFilePath
597 */
598 public void setXmlFilePath(String xmlFilePath) {
599 this.xmlFilePath = xmlFilePath;
600 }
601
602 /**
603 * The description of the component being demoed by this view
604 *
605 * @return the description
606 */
607 public String getDescription() {
608 return description;
609 }
610
611 /**
612 * Sets the description
613 *
614 * @param description
615 */
616 public void setDescription(String description) {
617 this.description = description;
618 }
619
620 /**
621 * Gets the usage description and examples of how to use this component
622 *
623 * @return the usage text
624 */
625 public String getUsage() {
626 return usage;
627 }
628
629 /**
630 * Set the usage text
631 *
632 * @param usage
633 */
634 public void setUsage(String usage) {
635 this.usage = usage;
636 }
637
638 /**
639 * The details group that will contain the description, usage, and properties tabGroup
640 *
641 * @return the details group
642 */
643 public Group getDetailsGroup() {
644 return detailsGroup;
645 }
646
647 /**
648 * Set the details group
649 *
650 * @param detailsGroup
651 */
652 public void setDetailsGroup(Group detailsGroup) {
653 this.detailsGroup = detailsGroup;
654 }
655
656 /**
657 * Gets the exhibit that will display the example, source code, and tabs to switch between examples
658 *
659 * @return the ComponentExhibit for this component demo view
660 */
661 public ComponentExhibit getExhibit() {
662 return exhibit;
663 }
664
665 /**
666 * Set the ComponentExhibit for this demo
667 *
668 * @param exhibit
669 */
670 public void setExhibit(ComponentExhibit exhibit) {
671 this.exhibit = exhibit;
672 }
673
674 /**
675 * List of groups that will demostrate the functionality fo the component being demonstrated, these groups are
676 * copied directly into componentExhibit - this is an ease of use property
677 *
678 * @return the demoGroups
679 */
680 public List<Group> getDemoGroups() {
681 return demoGroups;
682 }
683
684 /**
685 * Set the demoGroups used for demonstrating features of the component
686 *
687 * @param demoGroups
688 */
689 public void setDemoGroups(List<Group> demoGroups) {
690 this.demoGroups = demoGroups;
691 }
692
693 /**
694 * The root address to the javadoc for Rice
695 *
696 * @return the javadoc root address
697 */
698 public String getRootJavadocAddress() {
699 return rootJavadocAddress;
700 }
701
702 /**
703 * Set the root address to the javadoc for Rice
704 *
705 * @param rootJavadocAddress
706 */
707 public void setRootJavadocAddress(String rootJavadocAddress) {
708 this.rootJavadocAddress = rootJavadocAddress;
709 }
710
711 /**
712 * Get the root address to the docbook for KRAD
713 *
714 * @return KRAD's docbook address (url)
715 */
716 public String getRootDocBookAddress() {
717 return rootDocBookAddress;
718 }
719
720 /**
721 * Set the docbook root address
722 *
723 * @param rootDocBookAddress
724 */
725 public void setRootDocBookAddress(String rootDocBookAddress) {
726 this.rootDocBookAddress = rootDocBookAddress;
727 }
728
729 /**
730 * The anchor in the docbook this component is described at (do not include #)
731 *
732 * @return the anchor name
733 */
734 public String getDocBookAnchor() {
735 if (docBookAnchor == null) {
736 return "";
737 } else {
738 return "#" + docBookAnchor;
739 }
740 }
741
742 /**
743 * Set the docBookAnchor name for the component described by this view
744 *
745 * @param docBookAnchor
746 */
747 public void setDocBookAnchor(String docBookAnchor) {
748 this.docBookAnchor = docBookAnchor;
749 }
750
751 public ExampleSize getExampleSize() {
752 return exampleSize;
753 }
754
755 public void setExampleSize(ExampleSize exampleSize) {
756 this.exampleSize = exampleSize;
757 }
758
759 public String getLargeExampleFieldId() {
760 return largeExampleFieldId;
761 }
762
763 public void setLargeExampleFieldId(String largeExampleFieldId) {
764 this.largeExampleFieldId = largeExampleFieldId;
765 }
766
767 /**
768 * @see org.kuali.rice.krad.uif.component.ComponentBase#copy()
769 */
770 @Override
771 protected <T> void copyProperties(T component) {
772 super.copyProperties(component);
773
774 ComponentLibraryView libraryViewCopy = (ComponentLibraryView) component;
775
776 libraryViewCopy.setRootJavadocAddress(this.rootJavadocAddress);
777 libraryViewCopy.setRootDocBookAddress(this.rootDocBookAddress);
778 libraryViewCopy.setDocBookAnchor(this.docBookAnchor);
779 libraryViewCopy.setComponentName(this.componentName);
780 libraryViewCopy.setJavaFullClassPath(this.javaFullClassPath);
781 libraryViewCopy.setXmlFilePath(this.xmlFilePath);
782 libraryViewCopy.setDescription(this.description);
783 libraryViewCopy.setUsage(this.usage);
784 libraryViewCopy.setLargeExampleFieldId(this.largeExampleFieldId);
785 libraryViewCopy.setExampleSize(this.exampleSize);
786
787 if (this.detailsGroup != null) {
788 libraryViewCopy.setDetailsGroup((Group) this.detailsGroup.copy());
789 }
790
791 if (this.exhibit != null) {
792 libraryViewCopy.setExhibit((ComponentExhibit) this.exhibit.copy());
793 }
794
795 if (this.demoGroups != null) {
796 List<Group> demoGroupsCopy = new ArrayList<Group>();
797
798 for (Group demoGroup : this.demoGroups) {
799 demoGroupsCopy.add((Group) demoGroup.copy());
800 }
801 libraryViewCopy.setDemoGroups(demoGroupsCopy);
802 }
803 }
804 }