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