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