001/**
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: AttributeSchema.java,v 1.13 2009/01/13 06:56:08 mahesh_prasad_r Exp $
026 *
027 */
028
029/*
030 * Portions Copyrighted 2014 ForgeRock AS.
031 */
032
033package com.sun.identity.sm;
034
035import java.security.AccessController;
036import java.text.MessageFormat;
037import java.util.Collections;
038import java.util.HashMap;
039import java.util.HashSet;
040import java.util.Iterator;
041import java.util.Map;
042import java.util.Set;
043
044import org.w3c.dom.Document;
045import org.w3c.dom.Element;
046import org.w3c.dom.Node;
047
048import com.sun.identity.shared.debug.Debug;
049import com.sun.identity.shared.xml.XMLUtils;
050import com.iplanet.sso.SSOException;
051import com.sun.identity.security.EncodeAction;
052
053/**
054 * The class <code>AttributeSchema</code> provides methods to access the
055 * schema of a configuration parameter. Also, it provides methods to set default
056 * and choice values.
057 *
058 * @supported.all.api
059 */
060public class AttributeSchema {
061    // Debug
062    private static Debug debug = SMSEntry.debug;
063
064    // Instance variable
065    ServiceSchemaManager ssm;
066
067    ServiceSchema ss;
068
069    PluginSchema ps;
070
071    AttributeSchemaImpl as;
072
073    /**
074     * Constructor. Makes it private so that it cannot be instantiated.
075     */
076    private AttributeSchema() {
077    }
078
079    /**
080     * Constructor used by ServiceSchema to instantiate
081     * <code>AttributeSchema</code> objects.
082     */
083    protected AttributeSchema(AttributeSchemaImpl as, ServiceSchemaManager ssm,
084            ServiceSchema ss) {
085        this.ssm = ssm;
086        this.ss = ss;
087        this.as = as;
088        if (as == null) {
089            debug.error("AttributeSchema:: IMPL is NULL");
090        }
091    }
092
093    protected AttributeSchema(AttributeSchemaImpl as, PluginSchema ps) {
094        this.as = as;
095        this.ps = ps;
096    }
097
098    /**
099     * Returns the name of the attribute.
100     * 
101     * @return the name of the attribute
102     */
103    public String getName() {
104        return (as.getName());
105    }
106
107    /**
108     * Returns the type of the attribute.
109     * 
110     * @return the type of the attribute
111     */
112    public AttributeSchema.Type getType() {
113        return (as.getType());
114    }
115
116    /**
117     * Returns Service Schema.
118     * 
119     * @return Service Schema.
120     */
121    public ServiceSchema getServiceSchema() {
122        return ss;
123    }
124
125    /**
126     * Sets the type.
127     * 
128     * @param type
129     *            to be changed to
130     * @throws SMSException
131     *             if an error is encountered when trying to set
132     * @throws SSOException
133     *             if the single sign on token is invalid or expired
134     */
135    public void setType(String type) throws SMSException, SSOException {
136        updateXMLDocument(SMSUtils.ATTRIBUTE_TYPE, type);
137    }
138
139    /**
140     * Returns the list order of the attribute.
141     *
142     * @return The list order of the attribute, or {@code null} if the list order is not defined.
143     */
144    public AttributeSchema.ListOrder getListOrder() {
145        return as.getListOrder();
146    }
147
148    /**
149     * Returns the UI type of the attribute.
150     * 
151     * @return the UI type of the attribute; or null if the UI Type is not
152     *         defined
153     */
154    public AttributeSchema.UIType getUIType() {
155        return (as.getUIType());
156    }
157
158    /**
159     * Sets the <code>UIType</code> attribute.
160     * 
161     * @param uiType
162     *            user interface type.
163     * @throws SMSException
164     *             if an error is encountered when trying to set
165     *             <code>UIType</code> to the attribute schema.
166     * @throws SSOException
167     *             if the single sign on token is invalid or expired
168     */
169    public void setUIType(String uiType) throws SMSException, SSOException {
170        updateXMLDocument(SMSUtils.ATTRIBUTE_UITYPE, uiType);
171    }
172
173    /**
174     * Returns the syntax of the attribute.
175     * 
176     * @return the syntax of the attribute
177     */
178    public AttributeSchema.Syntax getSyntax() {
179        return (as.getSyntax());
180    }
181
182    /**
183     * Sets the Syntax attribute.
184     * 
185     * @param synt
186     *            syntax
187     * @throws SMSException
188     *             if an error is encountered when trying to set the attribute
189     *             syntax
190     * @throws SSOException
191     *             if the single sign on token is invalid or expired
192     */
193    public void setSyntax(String synt) throws SMSException, SSOException {
194        updateXMLDocument(SMSUtils.ATTRIBUTE_SYNTAX, synt);
195    }
196
197    /**
198     * Returns the I18N key to describe the configuration attribute.
199     * 
200     * @return the I18N key to describe the configuration attribute
201     */
202    public String getI18NKey() {
203        return (as.getI18NKey());
204    }
205
206    /**
207     * Sets the I18N key to describe the configuration attribute.
208     * 
209     * @param i18nKey
210     *            the I18N key to describe the attribute
211     * @throws SMSException
212     *             if an error is encountered when trying to set I18N key to the
213     *             attribute schema
214     * @throws SSOException
215     *             if the single sign on token is invalid or expired
216     */
217    public void setI18NKey(String i18nKey) throws SMSException, SSOException {
218        updateXMLDocument(SMSUtils.I18N_KEY, i18nKey);
219    }
220
221    /**
222     * Returns the value of the <code>cosQualifier</code> for this attribute
223     * that is <code>default, override, operational or merge-cos</code>.
224     * 
225     * @return the value of the <code>cosQualifier</code>.
226     */
227    public String getCosQualifier() {
228        return (as.getCosQualifier());
229    }
230
231    /**
232     * Sets the <code>cosQualifier</code> attribute
233     * 
234     * @param cosq
235     *            value of <code>cosQualifier</code>.
236     * @throws SMSException
237     *             if an error is encountered when trying to set.
238     * @throws SSOException
239     *             if the single sign on token is invalid or expired
240     */
241    public void setCosQualifier(String cosq) throws SMSException, SSOException {
242        updateXMLDocument(SMSUtils.ATTRIBUTE_COS_QUALIFIER, cosq);
243    }
244
245    /**
246     * Returns the default values of the attribute. If there are no default
247     * values defined for this attribute in the schema then this method returns
248     * a Collections.EMPTY_SET
249     * 
250     * @return set of default values of the attribute
251     */
252    public Set getDefaultValues() {
253        return (as.getDefaultValues());
254    }
255
256    /**
257     * Returns the default values of the attribute for the given environment
258     * parameters. If there are no default values defined for this attribute in
259     * the schema then this method returns a Collections.EMPTY_SET
260     * 
261     * @param envParams
262     *            Map of environment parameter to a set of values
263     * @return set of default values of the attribute
264     */
265    public Set getDefaultValues(Map envParams) {
266        return (as.getDefaultValues(envParams));
267    }
268
269    /**
270     * Sets the default values of the attribute.
271     * 
272     * @param values
273     *            the set of default values
274     * @throws SMSException
275     *             if an error is encountered when trying to set.
276     * @throws SSOException
277     *             if the single sign on token is invalid or expired
278     */
279    public void setDefaultValues(Set values) throws SMSException, SSOException {
280        updateDefaultValues(values);
281    }
282
283    /**
284     * Protected method to set the default values in the given XML document.
285     * 
286     * @throws SMSException
287     *             if an error is encountered when trying to set.
288     * @throws SSOException
289     *             if the single sign on token is invalid or expired
290     */
291    void setDefaultValues(Set values, Document document) throws SMSException,
292            SSOException {
293        updateDefaultValues(values, document);
294    }
295
296    /**
297     * Adds a default value to the existing set of default values.
298     * 
299     * @param value
300     *            the default value to add
301     * @throws SMSException
302     *             if an error is encountered when trying to set.
303     * @throws SSOException
304     *             if the single sign on token is invalid or expired
305     */
306    public void addDefaultValue(String value) throws SMSException, SSOException
307    {
308        Set defaultValues = getDefaultValues();
309        if (defaultValues != Collections.EMPTY_SET) {
310            defaultValues.add(value);
311        } else {
312            defaultValues = new HashSet();
313            defaultValues.add(value);
314        }
315        updateDefaultValues(defaultValues);
316    }
317
318    /**
319     * Removes the all the default values for the attribute.
320     * 
321     * @throws SMSException
322     *             if an error is encountered when trying to set.
323     * @throws SSOException
324     *             if the single sign on token is invalid or expired
325     * 
326     */
327    public void removeDefaultValues() throws SMSException, SSOException {
328        updateDefaultValues(new HashSet());
329    }
330
331    /**
332     * Removes the given value from the set of default values.
333     * 
334     * @param value
335     *            the default value to remove
336     * @throws SMSException
337     *             if an error is encountered when trying to set.
338     * @throws SSOException
339     *             if the single sign on token is invalid or expired
340     */
341    public void removeDefaultValue(String value) throws SMSException,
342            SSOException {
343        Set defaultValues = getDefaultValues();
344        if (defaultValues != Collections.EMPTY_SET) {
345            defaultValues.remove(value);
346            updateDefaultValues(defaultValues);
347        }
348    }
349
350    /**
351     * Returns the possible choice values for the attribute if the attribute
352     * type is either <code>SINGLE_CHOICE</code> or
353     * <code>MULTIPLE_CHOICE</code>.
354     * 
355     * @return set of possible choice values
356     */
357    public String[] getChoiceValues() {
358        return (as.getChoiceValues());
359    }
360
361    /**
362     * Returns the possible choice values for the attribute if the attribute
363     * type is either <code>SINGLE_CHOICE</code> or
364     * <code>MULTIPLE_CHOICE</code>, for the given environment parameters.
365     * 
366     * @param envParams
367     *            Map of environment parameter to a set of values
368     * @return set of possible choice values
369     */
370    public String[] getChoiceValues(Map envParams) {
371        return (as.getChoiceValues(envParams));
372    }
373
374    /**
375     * Returns the I18N key for the given choice value.
376     * 
377     * @param cValue
378     *            choice value.
379     * @return the I18N key for the given choice value
380     */
381    public String getChoiceValueI18NKey(String cValue) {
382        return (as.getChoiceValueI18NKey(cValue));
383    }
384
385    /**
386     * Adds a choice value and its i18n key to the existing set of choice
387     * values.
388     * 
389     * @param value
390     *            the choice value to add
391     * @param i18nKey
392     *            the I18N key for the choice value
393     * @throws SMSException
394     *             if an error is encountered when trying to set.
395     * @throws SSOException
396     *             if the single sign on token is invalid or expired
397     */
398    public void addChoiceValue(String value, String i18nKey)
399            throws SMSException, SSOException {
400        Map choiceValues = as.getChoiceValuesMap();
401        choiceValues.put(value, i18nKey);
402        updateChoiceValues(choiceValues);
403    }
404
405    /**
406     * Removes the given value from the set of choice values.
407     * 
408     * @param value
409     *            the choice value to remove
410     * @throws SMSException
411     *             if an error is encountered when trying to set.
412     * @throws SSOException
413     *             if the single sign on token is invalid or expired
414     */
415    public void removeChoiceValue(String value) throws SMSException,
416            SSOException {
417        Map choiceValues = as.getChoiceValuesMap();
418        if (choiceValues.remove(value) != null) {
419            updateChoiceValues(choiceValues);
420        }
421    }
422
423    /**
424     * Returns the start range if the attribute syntax is either
425     * <code>NUMBER_RANGE</code> or <code>DECIMAL_RANGE</code>.
426     * 
427     * @return the start range for the attribute value
428     */
429    public String getStartRange() {
430        return (as.getStartRange());
431    }
432
433    /**
434     * Sets the start range attribute.
435     * 
436     * @param stRange
437     *            start range.
438     * @throws SMSException
439     *             if an error is encountered when trying to set
440     * @throws SSOException
441     *             if the single sign on token is invalid or expired
442     */
443    public void setStartRange(String stRange) throws SMSException, SSOException
444    {
445        updateXMLDocument(SMSUtils.ATTRIBUTE_RANGE_START, stRange);
446    }
447
448    /**
449     * Returns the end range if the attribute syntax is either
450     * <code>NUMBER_RANGE</code> or <code>DECIMAL_RANGE</code>.
451     * 
452     * @return the end range for the attribute value
453     */
454    public String getEndRange() {
455        return (as.getEndRange());
456    }
457
458    /**
459     * Sets the end range Attribute.
460     * 
461     * @param edRange
462     *            end range.
463     * @throws SMSException
464     *             if an error is encountered when trying to set
465     * @throws SSOException
466     *             if the single sign on token is invalid or expired
467     */
468    public void setEndRange(String edRange) throws SMSException, SSOException {
469        updateXMLDocument(SMSUtils.ATTRIBUTE_RANGE_END, edRange);
470    }
471
472    /**
473     * Method to get the validator name for using to validate this service
474     * attribute
475     * 
476     * @return the validator name
477     */
478    public String getValidator() {
479        return (as.getValidator());
480    }
481
482    /**
483     * Sets the Validator attribute
484     * 
485     * @param valid
486     *            validator
487     * @throws SMSException
488     *             if an error is encountered when trying to set
489     * @throws SSOException
490     *             if the single sign on token is invalid or expired
491     */
492    public void setValidator(String valid) throws SMSException, SSOException {
493        updateXMLDocument(SMSUtils.ATTRIBUTE_VALIDATOR, valid);
494    }
495
496    /**
497     * Returns the minimum number of values for the attribute if the attribute
498     * is of type <code>MULTIPLE_CHOICE</code>.
499     * 
500     * @return the minimum number of values
501     */
502    public int getMinValue() {
503        return (as.getMinValue());
504    }
505
506    /**
507     * Sets the minimum value attribute.
508     * 
509     * @param minV
510     *            minimum value.
511     * @throws SMSException
512     *             if an error is encountered when trying to set
513     * @throws SSOException
514     *             if the single sign on token is invalid or expired
515     */
516    public void setMinValue(String minV) throws SMSException, SSOException {
517        updateXMLDocument(SMSUtils.ATTRIBUTE_MIN_VALUE, minV);
518    }
519
520    /**
521     * Returns the maximum number of values for the attribute if the attribute
522     * is of type <code>MULTIPLE_CHOICE</code>.
523     * 
524     * @return the maximum number of values
525     */
526    public int getMaxValue() {
527        return (as.getMaxValue());
528    }
529
530    /**
531     * Sets the maximum value attribute.
532     * 
533     * @param maxV
534     *            maximum value.
535     * @throws SMSException
536     *             if an error is encountered when trying to set
537     * @throws SSOException
538     *             if the single sign on token is invalid or expired
539     */
540    public void setMaxValue(String maxV) throws SMSException, SSOException {
541        updateXMLDocument(SMSUtils.ATTRIBUTE_MAX_VALUE, maxV);
542    }
543
544    /**
545     * Sets the boolean values of the attribute.
546     *
547     * @param trueValue string value for <code>BooleanTrueValue</code>.
548     * @param trueValueI18nKey <code>I18N</code> key for
549     *        <code>BooleanTrueValue</code>.
550     * @param falseValue string value for <code>BooleanFalseValue</code>.
551     * @param falseValueI18nKey <code>I18N</code> Key for
552     *        <code>BooleanFalseValue</code>.
553     * @throws SMSException if an error is encountered when trying to  set.
554     * @throws SSOException if the single sign on token is invalid or expired
555     */
556    public void setBooleanValues(
557        String trueValue,
558        String trueValueI18nKey,
559        String falseValue,
560        String falseValueI18nKey
561    ) throws SSOException, SMSException {
562      updateBooleanValues(trueValue, trueValueI18nKey,
563            falseValue, falseValueI18nKey, null);
564    }
565
566
567    /**
568     * Returns the string value for <code>BooleanTrueValue</code>.
569     * 
570     * @return the string value for <code>BooleanTrueValue</code>.
571     */
572    public String getTrueValue() {
573        return (as.getTrueValue());
574    }
575
576    /**
577     * Returns the <code>I18N</code> key for <code>BooleanTrueValue</code>.
578     * 
579     * @return the <code>I18N</code> key for <code>BooleanTrueValue</code>.
580     */
581    public String getTrueValueI18NKey() {
582        return (as.getTrueValueI18NKey());
583    }
584
585    /**
586     * Returns the string value for <code>BooleanFalseValue</code>.
587     * 
588     * @return the string value for <code>BooleanFalseValue</code>.
589     */
590    public String getFalseValue() {
591        return (as.getFalseValue());
592    }
593
594    /**
595     * Returns the <code>I18N</code> Key for <code>BooleanFalseValue</code>.
596     * 
597     * @return the <code>I18N</code> Key for <code>BooleanFalseValue</code>.
598     */
599    public String getFalseValueI18NKey() {
600        return (as.getFalseValueI18NKey());
601    }
602
603    /**
604     * Returns true if the attribute is an optional attribute.
605     * 
606     * @return true if the attribute is an optional attribute.
607     */
608    public boolean isOptional() {
609        return (as.isOptional());
610    }
611
612    /**
613     * Returns true if the attribute is a service identifier (i.e., in the case
614     * of LDAP it would be the COS Specifier attribute).
615     * 
616     * @return true if the attribute is service identifier attribute.
617     */
618    public boolean isServiceIdentifier() {
619        return (as.isServiceIdentifier());
620    }
621
622    /**
623     * Checks if the attribute allows to have resource name.
624     * 
625     * @return true if the attribute allows to have resource name; false
626     *         otherwise
627     */
628    public boolean isResourceNameAllowed() {
629        return (as.isResourceNameAllowed());
630    }
631
632    /**
633     * Returns true if the attribute is a service's status attribute.
634     * 
635     * @return true if the attribute is a status attribute.
636     */
637    public boolean isStatusAttribute() {
638        return (as.isStatusAttribute());
639    }
640
641    /**
642     * Method to get service specific attributes. It return the value of the
643     * "any" attribute, if set in the XML schema for the service
644     * 
645     * @return value of "any" attribute
646     */
647    public String getAny() {
648        return (as.getAny());
649    }
650
651    /**
652     * Sets the any attribute.
653     * 
654     * @param a
655     *            value for any attribute.
656     * @throws SMSException
657     *             if an error is encountered when trying to set.
658     * @throws SSOException
659     *             if the single sign on token is invalid or expired.
660     */
661    public void setAny(String a) throws SMSException, SSOException {
662        updateXMLDocument(SMSUtils.ATTRIBUTE_ANY, a);
663    }
664
665    /**
666     * Returns URL of the view bean for the attribute.
667     * 
668     * @return URL for view bean
669     */
670    public String getPropertiesViewBeanURL() {
671        return (as.getPropertiesViewBeanURL());
672    }
673
674    /**
675     * Sets the URL of the view bean for the attribute.
676     * 
677     * @param prop
678     *            properties view bean URL.
679     * @throws SMSException
680     *             if an error is encountered when trying to set.
681     * @throws SSOException
682     *             if the single sign on token is invalid or expired.
683     */
684    public void setPropertiesViewBeanUR(String prop) throws SMSException,
685            SSOException {
686        updateXMLDocument(SMSUtils.ATTRIBUTE_VIEW_BEAN_URL, prop);
687    }
688
689    /**
690     * Returns <code>true</code> if the attribute is searchable;
691     * <code>false</code> otherwise
692     * 
693     * @return <code>true</code> if the attribute is an optional attribute;
694     *         <code>false</code> otherwise
695     */
696    public boolean isSearchable() {
697        return (as.isSearchable());
698    }
699
700    /**
701     * Sets the attribute isSearchable, if value is set to <code>true
702     * </code>,
703     * or <code>false</code>.
704     * 
705     * @param value
706     *            if set to <code>true</code> the attribute will be
707     *            searchable; else searches cannot be performed on this
708     *            attribute.
709     * @throws SMSException
710     *             if an error is encountered when trying to set
711     * @throws SSOException
712     *             if the single sign on token is invalid or expired
713     */
714    public void setSearchable(String value) throws SMSException, SSOException {
715        if ((!(value.toLowerCase()).equals("yes"))
716                && (!(value.toLowerCase()).equals("no"))) {
717            String[] arg = { value };
718            debug.error("AttributeSchema: Invalid isSearchable value");
719            throw new SMSException(SMSEntry.bundle
720                    .getString("sms-invalid-searchable-value")
721                    + ":" + arg, "sms-invalid-searchable-value");
722        }
723        updateXMLDocument(SMSUtils.ISSEARCHABLE, value);
724    }
725
726    /**
727     * Returns a string representation of this <code> AttributeSchema </code>
728     * object.
729     * 
730     * @return String representation of this object
731     */
732    public String toString() {
733        return (as.toString());
734    }
735
736    /**
737     * Method for modifying default values
738     */
739    protected void updateDefaultValues(Set defaultValues) throws SMSException,
740            SSOException {
741        updateDefaultValues(defaultValues, null);
742    }
743
744    /**
745     * Method for modifying default values given the XML document
746     */
747    protected void updateDefaultValues(Set defaultValues, Document doc)
748            throws SMSException, SSOException {
749        // Check if the values are valid
750        if (ss != null) {
751            Map tempattrs = new HashMap(1);
752            tempattrs.put(getName(), defaultValues);
753            ss.validateAttributes(tempattrs);
754        }
755
756        // Check if the attributes have to be encoded
757        boolean encode = false;
758        if (getSyntax().equals(Syntax.PASSWORD)
759                || getSyntax().equals(Syntax.ENCRYPTED_PASSWORD)) {
760            encode = true;
761        }
762
763        // Construct DefaultValues node
764        StringBuffer sb = new StringBuffer(100);
765        sb.append(XML_PREFIX).append(DEFAULT_VALUES_BEGIN);
766        Iterator items = defaultValues.iterator();
767        while (items.hasNext()) {
768            sb.append(VALUE_BEGIN);
769            if (encode) {
770                String encString = (String) items.next();
771                try {
772                    encString = (String) AccessController
773                            .doPrivileged(new EncodeAction(encString));
774                } catch (Throwable e) {
775                    debug.error("AttributeSchema: Unable to encode", e);
776                }
777                sb.append(encString);
778            } else {
779                sb.append(SMSSchema.escapeSpecialCharacters((String) items
780                        .next()));
781            }
782            sb.append(VALUE_END);
783        }
784        sb.append(DEFAULT_VALUES_END);
785        updateXMLDocument(sb, SMSUtils.ATTRIBUTE_DEFAULT_ELEMENT, doc);
786    }
787
788    protected void updateChoiceValues(Map choiceValues) throws SMSException,
789            SSOException {
790        updateChoiceValues(choiceValues, null);
791    }
792
793     protected void updateChoiceValues(Map choiceValues, Document doc)
794            throws SMSException, SSOException {
795        // Construct ChoiceValues
796        StringBuffer sb = new StringBuffer(100);
797        sb.append(XML_PREFIX).append(CHOICE_VALUES_BEGIN);
798        Iterator items = choiceValues.keySet().iterator();
799        while (items.hasNext()) {
800            String[] vals = new String[2];
801            String value = SMSSchema.escapeSpecialCharacters((String) items
802                    .next());
803            String i18nKey = (String) choiceValues.get(value);
804            if (i18nKey == null) {
805                vals[0] = value;
806                sb.append(MessageFormat.format(CHOICE_VALUE, (Object[])vals));
807            } else {
808                vals[0] = i18nKey;
809                vals[1] = value;
810                sb.append(MessageFormat.format(
811                    CHOICE_VALUE_KEY, (Object[])vals));
812            }
813        }
814        sb.append(CHOICE_VALUES_END);
815        updateXMLDocument(sb, SMSUtils.ATTRIBUTE_CHOICE_VALUES_ELEMENT, doc);
816    }
817
818    protected void updateBooleanValues(
819        String trueValue,
820        String trueValueI18nKey,
821        String falseValue,
822        String falseValueI18nKey,
823        Document doc
824    ) throws SMSException, SSOException {
825      // Construct BooleanValues
826      StringBuffer sb = new StringBuffer(100);
827      sb.append(XML_PREFIX).append(BOOLEAN_VALUES_BEGIN);
828
829      String[] trueVals = new String[2];
830        if ((trueValueI18nKey != null) && (trueValue != null)) {
831            trueVals[0] = trueValueI18nKey;
832            trueVals[1] = SMSSchema.escapeSpecialCharacters(trueValue);
833        } else {
834            trueVals[0] = getTrueValueI18NKey();
835            trueVals[1] = getTrueValue();
836        }
837        sb.append(MessageFormat.format(TRUE_BOOLEAN_KEY, (Object[])trueVals));
838
839      String[] falseVals = new String[2];
840      if ((falseValueI18nKey != null) && (falseValue != null)) {
841          falseVals[0] = falseValueI18nKey;
842          falseVals[1] = SMSSchema.escapeSpecialCharacters(falseValue);
843      } else {
844            falseVals[0] = getFalseValueI18NKey();
845            falseVals[1] = getFalseValue();
846      }
847      sb.append(MessageFormat.format(FALSE_BOOLEAN_KEY, (Object[])falseVals));
848
849      sb.append(BOOLEAN_VALUES_END);
850      updateXMLDocument(sb, SMSUtils.ATTRIBUTE_BOOLEAN_VALUES_ELEMENT, doc);
851    }
852
853    protected void updateXMLDocument(StringBuffer sb, String elementName,
854            Document updateDoc) throws SMSException, SSOException {
855        // Update the default element in XML
856        try {
857            // Construct the XML document
858            Document doc = SMSSchema.getXMLDocument(sb.toString(), false);
859            Node node = XMLUtils.getRootNode(doc, elementName);
860
861            // Convert to Schema's document
862            Document schemaDoc = null;
863            if (updateDoc != null) {
864                schemaDoc = updateDoc;
865            } else if (ssm != null) {
866                schemaDoc = ssm.getDocumentCopy();
867            } else {
868                schemaDoc = ps.getDocumentCopy();
869            }
870            Node nNode = schemaDoc.importNode(node, true);
871
872            // Traverse the document to get this attribute element
873            Node schemaNode = null;
874            if (ss != null) {
875                schemaNode = ss.getSchemaNode(schemaDoc);
876            } else {
877                schemaNode = ps.getPluginSchemaNode(schemaDoc);
878            }
879            Node attrSchemaNode = XMLUtils.getNamedChildNode(schemaNode,
880                    SMSUtils.SCHEMA_ATTRIBUTE, SMSUtils.NAME, getName());
881
882            // Try getting OrganizationAttributeSchema if AttributeSchema
883            // node is not there within Organization node.
884            // This will be a special case for idrepo service.
885            if (attrSchemaNode == null) {
886                schemaNode = ss.getOrgAttrSchemaNode(schemaDoc);
887                attrSchemaNode = XMLUtils.getNamedChildNode(schemaNode,
888                    SMSUtils.SCHEMA_ATTRIBUTE, SMSUtils.NAME, getName());
889            }
890            Node oNode = XMLUtils.getChildNode(attrSchemaNode, elementName);
891            if (oNode != null) {
892                attrSchemaNode.replaceChild(nNode, oNode);
893            } else {
894                attrSchemaNode.appendChild(nNode);
895            }
896            // Update the schema in the directory
897            if (updateDoc != null) {
898                // do nothing
899            } else if (ssm != null) {
900                ssm.replaceSchema(schemaDoc);
901            } else {
902                ps.replacePluginSchema(schemaDoc);
903            }
904        } catch (Exception e) {
905            throw (new SMSException(e.getMessage(), e,
906                    "sms-cannot-update-xml-document"));
907        }
908    }
909
910    /**
911     * update attribute value in attribute schema element
912     */
913    protected void updateXMLDocument(String attrName, String attrValue)
914            throws SMSException, SSOException {
915        // Update the default element in XML
916        try {
917            // Construct the XML document
918            Document schemaDoc = null;
919            if (ssm != null) {
920                schemaDoc = ssm.getDocumentCopy();
921            } else {
922                schemaDoc = ps.getDocumentCopy();
923            }
924
925            // Traverse the document to get this attribute element
926            Node schemaNode = null;
927            if (ss != null) {
928                schemaNode = ss.getSchemaNode(schemaDoc);
929            } else {
930                schemaNode = ps.getPluginSchemaNode(schemaDoc);
931            }
932
933            Node attrSchemaNode = XMLUtils.getNamedChildNode(schemaNode,
934                    SMSUtils.SCHEMA_ATTRIBUTE, SMSUtils.NAME, getName());
935            ((Element) attrSchemaNode).setAttribute(attrName, attrValue);
936
937            // Update the schema in the directory
938            if (ssm != null) {
939                ssm.replaceSchema(schemaDoc);
940            } else {
941                ps.replacePluginSchema(schemaDoc);
942            }
943        } catch (Exception e) {
944            throw (new SMSException(e.getMessage(), e,
945                    "sms-cannot-update-xml-document"));
946        }
947    }
948
949    /**
950     * The class <code>Type</code> defines the types of schema attributes and
951     * provides static constants for these types. This could also be viewed as a
952     * higher level structured data types like Set, List, etc. The primitive
953     * data types are defined by <code>Syntax</code>. Currently defined
954     * schema attribute types are <code>SINGLE</code>, <code>LIST</code>,
955     * <code>SINGLE_CHOICE</code>, <code>MULTIPLE_CHOICE</code>,
956     * <code>SIGNATURE</code> and <code>VALIDATOR</code>.
957     */
958    public static class Type extends Object {
959
960        /**
961         * The <code>SINGLE</code> attribute type specifies that the attribute
962         * can have only a single value.
963         */
964        public static final Type SINGLE = new Type("single");
965
966        /**
967         * The <code>LIST</code> attribute type specifies that the attribute
968         * can have multiple values, i.e., multi-valued attribute.
969         */
970        public static final Type LIST = new Type("list");
971
972        /**
973         * The <code>SINGLE_CHOICE</code> attribute type specifies that the
974         * attribute can have value defined by the <code>getChoiceValues</code>
975         * method of <code>AttributeSchema</code>.
976         */
977        public static final Type SINGLE_CHOICE = new Type("single_choice");
978
979        /**
980         * The <code>MULTIPLE_CHOICE</code> attribute type specifies that the
981         * attribute can have multiple values defined by the
982         * <code>getChoiceValues</code> method of <code>AttributeSchema</code>.
983         */
984        public static final Type MULTIPLE_CHOICE = new Type("multiple_choice");
985
986        /**
987         * The <code>SIGNATURE</code> attribute type specifies that the
988         * attribute is a signing attribute.
989         */
990        public static final Type SIGNATURE = new Type("signature");
991
992        /**
993         * The <code>VALIDATOR</code> attribute type specifies that the
994         * attribute defines a attribute validator plugin.
995         */
996        public static final Type VALIDATOR = new Type("validator");
997
998        private String attrType;
999
1000        private Type() {
1001        }
1002
1003        private Type(String type) {
1004            attrType = type;
1005        }
1006
1007        /**
1008         * The method returns the string representation of the schema attribute
1009         * type.
1010         * 
1011         * @return String string representation of schema attribute type
1012         */
1013        public String toString() {
1014            return attrType;
1015        }
1016
1017        /**
1018         * Method to check if two schema attribute types are equal.
1019         * 
1020         * @param schemaAttrType
1021         *            the reference object with which to compare
1022         * 
1023         * @return <code>true</code> if the objects are same; <code>
1024         * false</code>
1025         *         otherwise
1026         */
1027        public boolean equals(Object schemaAttrType) {
1028            if (schemaAttrType instanceof Type) {
1029                Type s = (Type) schemaAttrType;
1030                return (s.attrType.equals(attrType));
1031            }
1032            return (false);
1033        }
1034
1035        /**
1036         * Returns a hash code value for the object.
1037         * 
1038         * @return a hash code value for the object
1039         */
1040        public int hashCode() {
1041            return attrType.hashCode();
1042        }
1043    }
1044
1045    /**
1046     * This enum {@code ListOrder} defines the list orders of schema attributes and provides constants for these list
1047     * orders. These types will mainly be used by the GUI to determine how to display the schema attributes.
1048     */
1049    public enum ListOrder {
1050        /** Orders lists naturally. */
1051        NATURAL,
1052        /** Orders lists in the order they are entered in LDAP. */
1053        INSERTION
1054    }
1055
1056    /**
1057     * The class <code>UIType</code> defines the UI types of schema attributes
1058     * and provides static constants for these types. These types mainly will be
1059     * used by the GUI to determine how to display the schema attributes.
1060     * Currently defined schema attribute UI types are <code>RADIO</code>,
1061     * <code>LINK</code>, <code>BUTTON</code> and
1062     * <code>NAME_VALUE_LIST</code>
1063     */
1064    public static class UIType extends Object {
1065
1066        /**
1067         * The <code>RADIO</code> attribute type specifies that the attribute
1068         * should be display as radio button.
1069         */
1070        public static final UIType RADIO = new UIType("radio");
1071
1072        /**
1073         * The <code>LINK</code> attribute type specifies that the attribute
1074         * should be display as a link.
1075         */
1076        public static final UIType LINK = new UIType("link");
1077
1078        /**
1079         * The <code>BUTTON</code> attribute type specifies that the attribute
1080         * should be display as a button.
1081         */
1082        public static final UIType BUTTON = new UIType("button");
1083
1084        /**
1085         * The <code>NAME_VALUE_LIST</code> attribute type specifies that the
1086         * attribute should be display as a name value list widget.
1087         */
1088        public static final UIType NAME_VALUE_LIST = new UIType(
1089            "name_value_list");
1090
1091        /**
1092         * The <code>UNORDERED_LIST</code> attribute type specifies that the
1093         * attribute should be display as an unordered list widget.
1094         */
1095        public static final UIType UNORDEREDLIST = new UIType("unorderedlist");
1096
1097        /**
1098         * The <code>ORDERED_LIST</code> attribute type specifies that the
1099         * attribute should be display as an ordered list widget.
1100         */
1101        public static final UIType ORDEREDLIST = new UIType("orderedlist");
1102
1103        /**
1104         * The <code>MAP_LIST</code> attribute type specifies that the
1105         * attribute should be display as an map list widget.
1106         */
1107        public static final UIType MAPLIST = new UIType("maplist");
1108
1109        /**
1110         * The <code>GLOBALMAP_LIST</code> attribute type specifies that the
1111         * attribute should be display as a global map list widget.
1112         */
1113        public static final UIType GLOBALMAPLIST = new UIType("globalmaplist");
1114        
1115        /**
1116         * The <code>ADDREMOVELIST</code> attribute type specifies that the
1117         * multiple choice attribute should be display as add remove list
1118         * widget.
1119         */
1120        public static final UIType ADDREMOVELIST = new UIType("addremovelist");
1121
1122        private String attrType;
1123
1124        private UIType() {
1125        }
1126
1127        private UIType(String type) {
1128            attrType = type;
1129        }
1130
1131        /**
1132         * The method returns the string representation of the schema attribute
1133         * UI type.
1134         * 
1135         * @return String string representation of schema attribute UI type
1136         */
1137        public String toString() {
1138            return attrType;
1139        }
1140
1141        /**
1142         * Method to check if two schema attribute UI types are equal.
1143         * 
1144         * @param schemaAttrType
1145         *            the reference object with which to compare
1146         * 
1147         * @return <code>true</code> if the objects are same; <code>
1148         * false</code>
1149         *         otherwise
1150         */
1151        public boolean equals(Object schemaAttrType) {
1152            if (schemaAttrType instanceof UIType) {
1153                UIType s = (UIType) schemaAttrType;
1154                return (s.attrType.equals(attrType));
1155            }
1156            return (false);
1157        }
1158
1159        /**
1160         * Returns a hash code value for the object.
1161         * 
1162         * @return a hash code value for the object
1163         */
1164        public int hashCode() {
1165            return attrType.hashCode();
1166        }
1167    }
1168
1169    /**
1170     * The class <code>Syntax</code> defines the syntax of the schema
1171     * attributes and provides static constants for these types. In other words,
1172     * this class defines the primitive data types for the schema attributes.
1173     */
1174    public static class Syntax {
1175
1176        /**
1177         * The <code>BOOLEAN</code> attribute syntax specifies that the
1178         * attribute is of boolean type, i.e., can have a value of either
1179         * <code>true</code> or <code>
1180         * false</code>
1181         */
1182        public static final Syntax BOOLEAN = new Syntax("boolean");
1183
1184        /**
1185         * The <code>EMAIL</code> attribute syntax specifies that the
1186         * attribute is a email address.
1187         */
1188        public static final Syntax EMAIL = new Syntax("email");
1189
1190        /**
1191         * The <code>URL</code> attribute syntax specifies that the attribute
1192         * is a URL.
1193         */
1194        public static final Syntax URL = new Syntax("url");
1195
1196        /**
1197         * The <code>STRING</code> attribute syntax specifies that the
1198         * attribute is of text type, i.e., can have any unicode characters.
1199         */
1200        public static final Syntax STRING = new Syntax("string");
1201
1202        /**
1203         * The <code>PARAGRAPH</code> attribute syntax specifies that the
1204         * attribute is of multi-lined text type.
1205         */
1206        public static final Syntax PARAGRAPH = new Syntax("paragraph");
1207
1208        /**
1209         * The <code>XML</code> attribute syntax specifies that the attribute
1210         * is of XML type, i.e., can have any unicode characters.
1211         */
1212        public static final Syntax XML = new Syntax("xml");
1213
1214        /**
1215         * The <code>SCRIPT</code> attribute syntax specifies that the
1216         * attribute is of multi-lined text type and more specifically a script.
1217         */
1218        public static final Syntax SCRIPT = new Syntax("script");
1219
1220        /**
1221         * The <code>PASSWORD</code> attribute syntax specifies that the
1222         * attribute is of password type, will be used by UI to mask the
1223         * password typed.
1224         */
1225        public static final Syntax PASSWORD = new Syntax("password");
1226
1227        /**
1228         * The <code>ENCRYPTED PASSWORD</code> attribute syntax specifies that
1229         * the attribute is of password type, will be used by UI to mask the
1230         * password typed.
1231         */
1232        public static final Syntax ENCRYPTED_PASSWORD = new Syntax(
1233                "encrypted_password");
1234
1235        /**
1236         * The <code>DATE</code> attribute syntax specifies that the attribute
1237         * is of date type.
1238         */
1239        public static final Syntax DATE = new Syntax("date");
1240
1241        /**
1242         * The <code>NUMERIC</code> attribute syntax specifies that the
1243         * attribute is numeric, i.e., can have numbers only.
1244         */
1245        public static final Syntax NUMERIC = new Syntax("numeric");
1246
1247        /**
1248         * The <code>NUMBER</code> attribute syntax specifies that the
1249         * attribute is a number.
1250         */
1251        public static final Syntax NUMBER = new Syntax("number");
1252
1253        /**
1254         * The <code>DECIMAL</code> attribute syntax specifies that the
1255         * attribute is a decimal value.
1256         */
1257        public static final Syntax DECIMAL = new Syntax("decimal");
1258
1259        /**
1260         * The <code>PERCENT</code> attribute syntax specifies that the
1261         * attribute is a percentage.
1262         */
1263        public static final Syntax PERCENT = new Syntax("percent");
1264
1265        /**
1266         * The <code>NUMBER_RANGE</code> attribute syntax specifies that the
1267         * attribute is a number within a range.
1268         */
1269        public static final Syntax NUMBER_RANGE = new Syntax("number_range");
1270
1271        /**
1272         * The <code>DECIMAL_RANGE</code> attribute syntax specifies that the
1273         * attribute is a decimal number within a range.
1274         */
1275        public static final Syntax DECIMAL_RANGE = new Syntax("decimal_range");
1276
1277        /**
1278         * The <code>DECIMAL_NUMBER</code> attribute syntax specifies that the
1279         * attribute is a floating point number, e.g., 1.5, 3.56, etc.
1280         */
1281        public static final Syntax DECIMAL_NUMBER = 
1282            new Syntax("decimal_number");
1283
1284        /**
1285         * The <code>DN</code> attribute syntax specifies that the attribute
1286         * should be an LDAP distinguished name (DN).
1287         */
1288        public static final Syntax DN = new Syntax("dn");
1289
1290        private String attrSyntax;
1291
1292        private Syntax() {
1293        }
1294
1295        private Syntax(String syntax) {
1296            attrSyntax = syntax;
1297        }
1298
1299        /**
1300         * The method returns the string representation of the schema attribute
1301         * syntax.
1302         * 
1303         * @return String string representation of schema attribute syntax
1304         */
1305        public String toString() {
1306            return (attrSyntax);
1307        }
1308
1309        /**
1310         * Method to check if two schema attribute syntax are equal.
1311         * 
1312         * @param schemaAttrSyntax
1313         *            the reference object with which to compare
1314         * 
1315         * @return <code>true</code> if the objects are same; <code>
1316         * false</code>
1317         *         otherwise
1318         */
1319        public boolean equals(Object schemaAttrSyntax) {
1320            if (schemaAttrSyntax instanceof Syntax) {
1321                Syntax s = (Syntax) schemaAttrSyntax;
1322                return (s.attrSyntax.equals(attrSyntax));
1323            }
1324            return (false);
1325        }
1326
1327        /**
1328         * Returns a hash code value for the object.
1329         * 
1330         * @return a hash code value for the object
1331         */
1332        public int hashCode() {
1333            return attrSyntax.hashCode();
1334        }
1335    }
1336
1337    private static final String XML_PREFIX = 
1338        "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
1339
1340    private static final String DEFAULT_VALUES_BEGIN = "<"
1341            + SMSUtils.ATTRIBUTE_DEFAULT_ELEMENT + ">";
1342
1343    private static final String DEFAULT_VALUES_END = "</"
1344            + SMSUtils.ATTRIBUTE_DEFAULT_ELEMENT + ">";
1345
1346    static final String VALUE_BEGIN = "<" + SMSUtils.ATTRIBUTE_VALUE + ">";
1347
1348    static final String VALUE_END = "</" + SMSUtils.ATTRIBUTE_VALUE + ">";
1349
1350    private static final String CHOICE_VALUES_BEGIN = "<"
1351            + SMSUtils.ATTRIBUTE_CHOICE_VALUES_ELEMENT + ">";
1352
1353    private static final String CHOICE_VALUES_END = "</"
1354            + SMSUtils.ATTRIBUTE_CHOICE_VALUES_ELEMENT + ">";
1355
1356    private static final String CHOICE_VALUE_KEY = "<"
1357            + SMSUtils.ATTRIBUTE_CHOICE_VALUE_ELEMENT + " " + SMSUtils.I18N_KEY
1358            + "=\"{0}\">{1}</" + SMSUtils.ATTRIBUTE_CHOICE_VALUE_ELEMENT + ">";
1359
1360    private static final String CHOICE_VALUE = "<"
1361            + SMSUtils.ATTRIBUTE_CHOICE_VALUE_ELEMENT + ">{0}</"
1362            + SMSUtils.ATTRIBUTE_CHOICE_VALUE_ELEMENT + ">";
1363
1364    private static final String BOOLEAN_VALUES_BEGIN =
1365      "<" + SMSUtils.ATTRIBUTE_BOOLEAN_VALUES_ELEMENT + ">";
1366
1367    private static final String BOOLEAN_VALUES_END =
1368      "</" + SMSUtils.ATTRIBUTE_BOOLEAN_VALUES_ELEMENT + ">";
1369
1370    private static final String TRUE_BOOLEAN_KEY =
1371      "<" + SMSUtils.ATTRIBUTE_TRUE_BOOLEAN_ELEMENT +
1372      " " + SMSUtils.I18N_KEY + "=\"{0}\">{1}</" +
1373      SMSUtils.ATTRIBUTE_TRUE_BOOLEAN_ELEMENT + ">";
1374
1375    private static final String FALSE_BOOLEAN_KEY =
1376      "<" + SMSUtils.ATTRIBUTE_FALSE_BOOLEAN_ELEMENT +
1377      " " + SMSUtils.I18N_KEY + "=\"{0}\">{1}</" +
1378      SMSUtils.ATTRIBUTE_FALSE_BOOLEAN_ELEMENT + ">";
1379}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.