1   /*
2    * Copyright 2003 - 2013 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.beans;
22  
23  import java.util.ArrayList;
24  import java.util.HashSet;
25  import java.util.Set;
26  
27  import org.efaps.admin.datamodel.Attribute;
28  import org.efaps.admin.datamodel.ui.FieldValue;
29  import org.efaps.admin.ui.AbstractUserInterfaceObject.TargetMode;
30  import org.efaps.db.AbstractPrintQuery;
31  import org.efaps.db.Instance;
32  import org.efaps.util.EFapsException;
33  import org.slf4j.Logger;
34  import org.slf4j.LoggerFactory;
35  
36  /**
37   * This class work together with the generated classes of the kernel
38   * (org.efpas.beans.valueparser) to get the Values for a String expression
39   * defined as a DBProperty like: "$< Type> '$< Name>': Details" from the
40   * eFaps-DataBase. The Values for an expression ("$< Type>") retrieved from the
41   * eFaps-DataBase will be combined with pure Text ("Details").
42   *
43   * @author The eFaps Team
44   * @version $Id$
45   */
46  public class ValueList
47  {
48      /**
49       * Logging instance used in this class.
50       */
51      private static final Logger LOG = LoggerFactory.getLogger(ValueList.class);
52  
53      /**
54       * Enum used to differ expression parts from text parts.
55       */
56      public enum TokenType
57      {
58          /** Used for token of type expression. */
59          EXPRESSION,
60          /** Used for token of type text. */
61          TEXT
62      }
63  
64      /**
65       * Holds the Expressions used in this ValueList.
66       */
67      private final Set<String> expressions = new HashSet<String>();
68  
69      /**
70       * Holds the tokens of this ValueList.
71       */
72      private final ArrayList<Token> tokens = new ArrayList<Token>();
73  
74      /**
75       * Getter method for instance variable {@link #tokens}.
76       *
77       * @return value of instance variable {@link #tokens}
78       */
79      public ArrayList<Token> getTokens()
80      {
81          return this.tokens;
82      }
83  
84      /**
85       * Get the ValueList.
86       *
87       * @return String with the Values, which looks like the original
88       */
89      public String getValueList()
90      {
91          final StringBuffer buf = new StringBuffer();
92  
93          for (final Token token : this.tokens) {
94              switch (token.type) {
95                  case EXPRESSION:
96                      buf.append("$<").append(token.value).append(">");
97                      break;
98                  case TEXT:
99                      buf.append(token.value);
100                     break;
101                 default:
102                     break;
103             }
104         }
105         return buf.toString();
106     }
107 
108     /**
109      * Add an Expression to this ValueList.
110      *
111      * @param _expression String with the expression
112      */
113     public void addExpression(final String _expression)
114     {
115         this.tokens.add(new Token(ValueList.TokenType.EXPRESSION, _expression));
116         getExpressions().add(_expression);
117     }
118 
119     /**
120      * Add Text to the Tokens.
121      *
122      * @param _text Text to be added
123      */
124     public void addText(final String _text)
125     {
126         this.tokens.add(new Token(ValueList.TokenType.TEXT, _text));
127     }
128 
129     /**
130      * This method adds the expressions of this ValueList to the given query.
131      *
132      * @param _print PrintQuery the expressions should be added
133      * @throws EFapsException on error
134      * @see {@link #makeString(AbstractQuery)}
135      */
136     public void makeSelect(final AbstractPrintQuery _print)
137         throws EFapsException
138     {
139         for (final String expression : getExpressions()) {
140             // TODO remove, only selects allowed
141             if (_print.getMainType().getAttributes().containsKey(expression)) {
142                 _print.addAttribute(expression);
143                 ValueList.LOG.warn(
144                                "The arguments for ValueList must only contain selects. Invalid: '{}' for ValueList: {}",
145                                 expression, getValueList());
146             } else if (expression.contains("[") || expression.equals(expression.toLowerCase())) {
147                 _print.addSelect(expression);
148             } else {
149                  ValueList.LOG.warn(
150                                "The arguments for ValueList must only contain selects. Invalid: '{}' for ValueList: {}",
151                                     expression, getValueList());
152             }
153         }
154     }
155 
156     /**
157      * This method retrieves the Values from the given PrintQuery and
158      * combines them with the Text partes.
159      *
160      * @param _callInstance instance on which the query was called
161      * @param _print        AbstractPrintQuery the ValueString should be retrieved
162      * @param _mode         target mode
163      * @return String with the actuall Value of this ValueList
164      * @throws EFapsException on error
165      * @see {@link #makeSelect(AbstractQuery)}
166      *
167      */
168     public String makeString(final Instance _callInstance,
169                              final AbstractPrintQuery _print,
170                              final TargetMode _mode)
171         throws EFapsException
172     {
173         final StringBuilder buf = new StringBuilder();
174 
175         for (final Token token : this.tokens) {
176             switch (token.type) {
177                 case EXPRESSION:
178                     Attribute attr = null;
179                     Object value = null;
180                     if (_print.getMainType().getAttributes().containsKey(token.value)) {
181                         attr = _print.getAttribute4Attribute(token.value);
182                         value = _print.getAttribute(token.value);
183                     } else {
184                         attr = _print.getAttribute4Select(token.value);
185                         value = _print.getSelect(token.value);
186                     }
187                     if (attr != null) {
188                         buf.append((new FieldValue(null, attr, value, null, _callInstance)).getStringValue(_mode));
189                     } else if (value != null) {
190                         buf.append(value);
191                     }
192                     break;
193                 case TEXT:
194                     buf.append(token.value);
195                     break;
196                 default:
197                     break;
198             }
199         }
200         return buf.toString();
201     }
202 
203     /**
204      * This is the getter method for the instance variable {@link #expressions}.
205      *
206      * @return value of instance variable {@link #expressions}
207      * @see #expressions
208      */
209     public Set<String> getExpressions()
210     {
211         return this.expressions;
212     }
213 
214     /**
215      * This class holds the definitions of the ValueList.
216      */
217     public final class Token
218     {
219         /**
220          * This instance variable holds the Type of this token.
221          */
222         private final TokenType type;
223 
224         /**
225          * This instance variable holds the value of this token.
226          */
227         private final String value;
228 
229         /**
230          * Constructor setting the instance variables.
231          *
232          * @param _type TokenType
233          * @param _value Value for the token
234          */
235         private Token(final TokenType _type,
236                       final String _value)
237         {
238             this.type = _type;
239             this.value = _value;
240         }
241 
242         /**
243          * Getter method for instance variable {@link #type}.
244          *
245          * @return value of instance variable {@link #type}
246          */
247         public TokenType getType()
248         {
249             return this.type;
250         }
251 
252         /**
253          * Getter method for instance variable {@link #value}.
254          *
255          * @return value of instance variable {@link #value}
256          */
257         public String getValue()
258         {
259             return this.value;
260         }
261     }
262 }