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: CreationTemplate.java,v 1.4 2008/06/25 05:41:44 qcheng Exp $
026 *
027 */
028
029/**
030 * Portions Copyrighted [2011] [ForgeRock AS]
031 */
032package com.iplanet.ums;
033
034import java.util.ArrayList;
035import java.util.Enumeration;
036import java.util.Vector;
037
038import com.iplanet.services.ldap.Attr;
039import com.iplanet.services.ldap.AttrSet;
040import com.iplanet.services.util.I18n;
041import com.iplanet.ums.validation.DataConstraintException;
042import com.iplanet.ums.validation.Validation;
043import com.iplanet.ums.validation.ValidationElement;
044
045/**
046 * Represents templates for creating objects in UMS. CreationTemplate is used to
047 * aid in creating objects in which it serves as reusable guidelines to
048 * instantiate UMS objects properly at runtime. The guidelines are used to
049 * instantiate objects in memory correctly so that subsequent storage in
050 * persistent storage can be done successfully. It is the intention that
051 * CreationTemplate allows applications to determine what is correct so that
052 * some control is given in the application for early detection of problems of
053 * UMS object creations. Reusability and flexibility are two desired goals of
054 * CreationTemplate.
055 * 
056 * @see Template
057 * @see SearchTemplate
058 *
059 * @supported.api
060 */
061public class CreationTemplate extends Template {
062
063    private static I18n i18n = I18n.getInstance(IUMSConstants.UMS_PKG);
064
065    /**
066     * Default constructor for deserialization
067     * 
068     */
069    public CreationTemplate() {
070        super();
071    }
072
073    /**
074     * Creates a template with required and optional attributes.
075     * 
076     * @param name
077     *            Template name
078     * @param required
079     *            Set of required attributes
080     * @param optional
081     *            Set of optional attributes
082     * @param classes
083     *            Array of classes that this CreationTemplate is associated with
084     *            for object creation
085     */
086    public CreationTemplate(String name, AttrSet required, AttrSet optional,
087            ArrayList classes) {
088        super(name);
089        setRequiredAttributeSet(required);
090        setOptionalAttributeSet(optional);
091        setCreationClasses(classes);
092    }
093
094    /**
095     * Creates a template with required and optional attributes.
096     * 
097     * @param name
098     *            Template name
099     * @param required
100     *            Set of required attributes
101     * @param optional
102     *            Set of optional attributes
103     * @param cls
104     *            Class that this CreationTemplate is associated with for object
105     *            creation
106     */
107    public CreationTemplate(String name, AttrSet required, AttrSet optional,
108            Class cls) {
109        this(name, required, optional);
110        ArrayList classes = new ArrayList();
111        classes.add(cls);
112        setCreationClasses(classes);
113    }
114
115    /**
116     * Creates a template with required and optional attributes.
117     * 
118     * @param name
119     *            Template name
120     * @param required
121     *            Set of required attributes
122     * @param optional
123     *            Set of optional attributes
124     */
125    public CreationTemplate(String name, AttrSet required, AttrSet optional) {
126        // No definition for the class
127        //
128        // this( name, required, optional, null );
129        super(name);
130        setRequiredAttributeSet(required);
131        setOptionalAttributeSet(optional);
132    }
133
134    /**
135     * Gets the value of a given attribute in the template.
136     * 
137     * @param attributeName
138     *            Name of attribute for which to return values
139     * @return The attribute with the specified name, or <CODE>null</CODE> if
140     *         attributeName is <CODE>null</CODE>, or the attribute is not
141     *         found.
142     * 
143     * @supported.api
144     */
145    public Attr getAttribute(String attributeName) {
146        if (attributeName == null) {
147            return null;
148        }
149        Attr attr = null;
150        if (m_required != null) {
151            attr = m_required.getAttribute(attributeName);
152        }
153        if ((attr == null) && (m_optional != null)) {
154            attr = m_optional.getAttribute(attributeName);
155        }
156        return attr;
157    }
158
159    /**
160     * Gets a list of required attribute names defined in the object.
161     * 
162     * @return Names of all required attributes defined
163     * 
164     * @supported.api
165     */
166    public String[] getRequiredAttributeNames() {
167        return (m_required == null) ? new String[0] : m_required
168                .getAttributeNames();
169    }
170
171    /**
172     * Gets a list of optional attribute names defined in the object.
173     * 
174     * @return Names of all optional attributes defined
175     * 
176     * @supported.api
177     */
178    public String[] getOptionalAttributeNames() {
179        return (m_optional == null) ? new String[0] : m_optional
180                .getAttributeNames();
181    }
182
183    /**
184     * Gets the required attributes for object creation.
185     * 
186     * @return set of required attributes
187     * 
188     * @supported.api
189     */
190    public AttrSet getRequiredAttributeSet() {
191        return m_required;
192    }
193
194    /**
195     * Gets the optional attributes for object creation.
196     * 
197     * @return set of optional attributes
198     * 
199     * @supported.api
200     */
201    public AttrSet getOptionalAttributeSet() {
202        return m_optional;
203    }
204
205    /**
206     * Get the classes that the CreationTemplate is associated with.
207     * 
208     * @return classes associated with this template
209     * 
210     * @supported.api
211     */
212    public ArrayList getCreationClasses() {
213        return m_classes;
214    }
215
216    /**
217     * Gets enumeration of ValidationElement for the attribute name
218     * 
219     * @param attrName
220     *            Attribute name
221     * @return Enumeration of ValidationElement
222     * 
223     * @supported.api
224     */
225    public Enumeration getValidation(String attrName) {
226        Vector v = new Vector();
227        if (attrName != null && m_validated != null) {
228            Attr attr = m_validated.getAttribute(attrName);
229            if (attr != null) {
230                String[] validationStrings = attr.getStringValues();
231                for (int i = 0; i < validationStrings.length; i++) {
232                    v.add(decodeValidationString(validationStrings[i]));
233                }
234            }
235        }
236        return v.elements();
237    }
238
239    AttrSet getValidation() {
240        return m_validated;
241    }
242
243    /**
244     * Gets a list of attribute names registered for validation.
245     * 
246     * @return a list of attribute names registered for validation
247     * 
248     * @supported.api
249     */
250    public String[] getValidatedAttributeNames() {
251        return (m_validated == null) ? new String[0] : m_validated
252                .getAttributeNames();
253    }
254
255    /**
256     * Gets enumeration of attributes for object creation.
257     * 
258     * @return enumeration of required and optional attributes
259     */
260    public Enumeration getAttributes() {
261        Vector v = new Vector();
262        if (m_required != null) {
263            for (int i = 0; i < m_required.size(); i++) {
264                v.add(m_required.elementAt(i));
265            }
266        }
267
268        if (m_optional != null) {
269            for (int i = 0; i < m_optional.size(); i++) {
270                v.add(m_optional.elementAt(i));
271            }
272        }
273
274        return v.elements();
275    }
276
277    /**
278     * Sets the required attributes.
279     * 
280     * @param attrSet
281     *            set of required attributes
282     */
283    public void setRequiredAttributeSet(AttrSet attrSet) {
284        // ??? Should we clone attrSet instead of keeping a reference?
285        m_required = attrSet;
286    }
287
288    /**
289     * Sets the optional attributes.
290     * 
291     * @param attrSet
292     *            set of optional attributes
293     */
294    public void setOptionalAttributeSet(AttrSet attrSet) {
295        // ??? Should we clone attrSet instead of keeping a reference?
296        m_optional = attrSet;
297    }
298
299    /**
300     * Set the class that the CreationTemplate is associated with.
301     * 
302     * @param classes
303     *            Classes associated with this template
304     */
305    public void setCreationClasses(ArrayList classes) {
306        m_classes = classes;
307    }
308
309    /**
310     * Adds the attribute to the required attributes.
311     * 
312     * @param attr
313     *            The attribute to be added
314     */
315    public void addRequiredAttribute(Attr attr) {
316        if (m_required == null) {
317            m_required = new AttrSet();
318        }
319        m_required.add(attr);
320    }
321
322    /**
323     * Adds the attribute to the optional attributes.
324     * 
325     * @param attr
326     *            The attribute to be added
327     */
328    public void addOptionalAttribute(Attr attr) {
329        if (m_optional == null) {
330            m_optional = new AttrSet();
331        }
332        m_optional.add(attr);
333    }
334
335    /**
336     * Sets the validation table
337     * 
338     * @param attrSet
339     *            validation table in attribute set format
340     */
341    void setValidation(AttrSet attrSet) {
342        // ??? Should we clone attrSet instead of keeping a reference?
343        m_validated = attrSet;
344    }
345
346    /**
347     * Adds the validator and the rule for the attribute name.
348     * 
349     * @param attrName Attribute name to validate.
350     * @param validatorClass Validator class name used for validation.
351     * @param rule The optional rule used by the validator.
352     */
353    public void addValidation(
354        String attrName,
355        String validatorClass,
356        String rule
357    ) {
358        if (validatorClass != null && attrName != null) {
359            String validationString = encodeValidationString(validatorClass,
360                    rule);
361            if (validationString != null) {
362                if (m_validated == null) {
363                    m_validated = new AttrSet();
364                }
365                if (!m_validated.contains(attrName, validationString)) {
366                    m_validated.add(new Attr(attrName, validationString));
367                }
368            }
369        }
370    }
371
372    /**
373     * Removes all validations from the attribute.
374     * 
375     * @param attrName
376     *            attribute name of the validations to be removed
377     */
378    public void removeValidation(String attrName) {
379        if (m_validated != null) {
380            m_validated.remove(attrName);
381        }
382    }
383
384    /**
385     * Sets the naming attribute.
386     * 
387     * @param namingAttribute
388     *            naming attribute
389     */
390    void setNamingAttribute(String namingAttribute) {
391        m_namingAttribute = namingAttribute;
392    }
393
394    /**
395     * Gets the naming attribute.
396     * 
397     * @return the naming attribute
398     * 
399     * @supported.api
400     */
401    public String getNamingAttribute() {
402        return m_namingAttribute;
403    }
404
405    /**
406     * Returns a copy of the template.
407     * 
408     * @return a copy of the template
409     * 
410     * @supported.api
411     */
412    public Object clone() {
413        CreationTemplate t = (CreationTemplate) super.clone();
414        if (m_required != null) {
415            t.setRequiredAttributeSet((AttrSet) m_required.clone());
416        }
417        if (m_optional != null) {
418            t.setOptionalAttributeSet((AttrSet) m_optional.clone());
419        }
420        if (m_validated != null) {
421            t.setValidation((AttrSet) m_validated.clone());
422        }
423        return t;
424    }
425
426    /**
427     * Encode an attrSet in a single attribute with multiple values using the
428     * given attribute name and the values (tag,value) found in the given
429     * attribute set. For example:
430     * 
431     * <pre>
432     *       required: objectclass=top
433     *       required: objectclass=groupofuniquenames
434     *       required: cn
435     *       required: sn
436     * </pre>
437     * 
438     * @param attrName
439     *            Name of the encoded attribute
440     * @param attrSet
441     *            Attribute Set to be encoded in a single attribute
442     * @param delimiter
443     *            String token used as delimiter for the encoding
444     * @return Encoded attribute or null object if attrSet is empty
445     */
446    static Attr encodeAttrSet(String attrName, AttrSet attrSet, 
447            String delimiter) 
448    {
449        if (attrSet == null || attrSet.size() == 0) {
450            return null;
451        }
452
453        Enumeration attrEnum = attrSet.getAttributes();
454        Attr encodedAttr = new Attr(attrName);
455
456        while (attrEnum.hasMoreElements()) {
457            Attr a = (Attr) attrEnum.nextElement();
458            String[] values = a.getStringValues();
459            String[] encodedValues = new String[values.length];
460
461            if (values.length == 0) {
462                encodedAttr.addValue(a.getName());
463            } else {
464                for (int i = 0; i < values.length; i++) {
465                    encodedValues[i] = a.getName() + delimiter + values[i];
466                }
467                encodedAttr.addValues(encodedValues);
468            }
469        }
470
471        return encodedAttr;
472    }
473
474    private static String encodeValidationString(String className, String rule)
475    {
476        if (rule == null) {
477            return className;
478        }
479        StringBuilder sb = new StringBuilder();
480        sb.append(className);
481        sb.append("(");
482        sb.append(rule);
483        sb.append(")");
484        return sb.toString();
485    }
486
487    private static ValidationElement decodeValidationString(String value) {
488        int index = value.indexOf('(');
489        if (index < 0) {
490            return (new ValidationElement(value, null));
491        }
492        String className = value.substring(0, index);
493        String rule = value.substring(index + 1, value.length() - 1);
494        return (new ValidationElement(className, rule));
495    }
496
497    /**
498     * Render the object.
499     * 
500     * @return The object in printable form
501     * 
502     * @supported.api
503     */
504    public String toString() {
505        return "CreationTemplate: " + getName() + " { Required " + m_required
506                + " Optional " + m_optional + " Validation " + m_validated
507                + " Naming Attribute " + m_namingAttribute + " }";
508    }
509
510    /**
511     * Validate attrSet according to the definition of required and optional
512     * attributes defined in the template.
513     * 
514     * @param attrSet
515     *            Attribute set to be validated
516     * @return true if the given attrSet conforms to the template
517     * @throws UMSException
518     *             if attrSet doesn't conform to the template
519     */
520    boolean validateAttrSet(AttrSet attrSet) throws UMSException {
521        AttrSet reqAttrs = getRequiredAttributeSet();
522        AttrSet optionalAttrs = getOptionalAttributeSet();
523        if (reqAttrs == null && optionalAttrs == null) {
524            throw new UMSException(i18n
525                    .getString(IUMSConstants.TEMPLATE_NO_ATTR));
526        }
527        String[] attrNames = attrSet.getAttributeNames();
528        int attrSetSize = (attrNames != null) ? attrNames.length : -1;
529        String attrName = null;
530
531        // Loop on attributes in the template comparing with the argument
532        // attSet and ensure all required attributtes are supplied
533        // or have a default
534        if (reqAttrs != null) {
535            Enumeration attrEnum = reqAttrs.getAttributes();
536            while (attrEnum.hasMoreElements()) {
537                Attr anAttr = (Attr) attrEnum.nextElement();
538                // if ( !attrSet.contains(anAttr.getName().toLowerCase())) {
539                if (!attrSet.contains(anAttr.getName())) {
540                    // A required attribute which was not supplied
541                    if (anAttr.size() > 0) {
542                        // There is a default value
543                        attrSet.add((Attr) anAttr.clone());
544                    } else {
545                        // No default value. This is an error! A value
546                        // should have been supplied in attrSet.
547                        attrName = anAttr.getName();
548                        String args[] = new String[1];
549                        args[0] = attrName;
550                        String msg = i18n.getString(IUMSConstants.NO_VALUE,
551                                args);
552                        throw new UMSException(msg);
553                    }
554                }
555            }
556        }
557
558        // If the optional attributes set is set to "*", which means allowing
559        // all attributes, then no need to ensure the given attributes are in
560        // either the required attributes set or the optional attributes set
561        if (optionalAttrs != null && optionalAttrs.contains("*")) {
562            return true;
563        }
564
565        // Loop on attributes in the argument attrSet comparing with the
566        // template and ensure all the attributes are allowed
567        //
568        boolean attrAllowed = false;
569        for (int i = 0; i < attrSetSize; i++) {
570            attrAllowed = false;
571            attrName = attrNames[i];
572            if (reqAttrs != null && reqAttrs.contains(attrName)) {
573                attrAllowed = true;
574            } else if (optionalAttrs != null
575                    && optionalAttrs.contains(attrName)) {
576                attrAllowed = true;
577            }
578            if (!attrAllowed) {
579                String args[] = new String[1];
580                args[0] = attrName;
581                String msg = i18n.getString(IUMSConstants.ATTR_NOT_ALLOWED,
582                        args);
583                // TODO: need to define new and meaningful exception for
584                // unknown attribute not conforming to the
585                // given creation template
586                //
587                throw new UMSException(msg);
588            }
589        }
590        return true;
591    }
592
593    /**
594     * Validate attrSet according to the definition of validated attributes
595     * defined in the template.
596     * 
597     * @param attrSet
598     *            Attribute set to be validated
599     * @return true if the given attrSet conforms to the template
600     * @throws DataConstraintException
601     *             if attrSet doesn't conform to the template
602     * @throws UMSException
603     *             failure
604     */
605    boolean validateAttributes(AttrSet attrSet) throws UMSException,
606            DataConstraintException {
607
608        Enumeration en1 = attrSet.getAttributes();
609        while (en1.hasMoreElements()) {
610            Attr attr = (Attr) en1.nextElement();
611            Enumeration en2 = getValidation(attr.getName());
612            while (en2.hasMoreElements()) {
613                ValidationElement vElement = (ValidationElement) en2
614                        .nextElement();
615                // calls method in Validation to validate each values
616                // of the attribute
617                Validation.validateAttribute(attr, vElement.getValidator(),
618                        vElement.getRule());
619            }
620        }
621        return true;
622    }
623
624    private AttrSet m_required = null;
625
626    private AttrSet m_optional = null;
627
628    private ArrayList m_classes = null;
629
630    private AttrSet m_validated = null;
631
632    private String m_namingAttribute = null;
633}




























































Copyright © 2010-2017, ForgeRock All Rights Reserved.