View Javadoc

1   /* 
2    * Copyright (c) 2007, Fraunhofer-Gesellschaft
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are
7    * met:
8    * 
9    * (1) Redistributions of source code must retain the above copyright
10   *     notice, this list of conditions and the disclaimer at the end.
11   *     Redistributions in binary form must reproduce the above copyright
12   *     notice, this list of conditions and the following disclaimer in
13   *     the documentation and/or other materials provided with the
14   *     distribution.
15   * 
16   * (2) Neither the name of Fraunhofer nor the names of its
17   *     contributors may be used to endorse or promote products derived
18   *     from this software without specific prior written permission.
19   * 
20   * DISCLAIMER
21   * 
22   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26   * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   *  
34   */
35  package org.ogf.graap.wsag.server.monitoring;
36  
37  import java.math.BigDecimal;
38  import java.util.Map;
39  
40  import org.apache.commons.jexl2.Expression;
41  import org.apache.commons.jexl2.JexlContext;
42  import org.apache.commons.jexl2.JexlEngine;
43  import org.apache.log4j.Logger;
44  import org.apache.xmlbeans.XmlObject;
45  import org.apache.xmlbeans.XmlString;
46  import org.ogf.graap.wsag.server.accounting.AccountingContext;
47  import org.ogf.graap.wsag.server.accounting.IAccountingContext;
48  import org.ogf.graap.wsag.server.accounting.IAccountingSystem;
49  import org.ogf.graap.wsag.server.accounting.SimpleAccountingSystemLogger;
50  import org.ogf.graap.wsag4j.types.engine.GuaranteeEvaluationResultType;
51  import org.ogf.graap.wsag4j.types.engine.SLOEvaluationResultType;
52  import org.ogf.schemas.graap.wsAgreement.AgreementPropertiesType;
53  import org.ogf.schemas.graap.wsAgreement.CompensationType;
54  import org.ogf.schemas.graap.wsAgreement.GuaranteeTermStateDefinition;
55  import org.ogf.schemas.graap.wsAgreement.GuaranteeTermStateType;
56  import org.ogf.schemas.graap.wsAgreement.GuaranteeTermType;
57  import org.ogf.schemas.graap.wsAgreement.ServiceLevelObjectiveType;
58  
59  /**
60   * Default implementation of a guarantee evaluator. The guarantee evaluator evaluates the qualifying condition
61   * and service level objective of a given guarantee and returns the guarantee term state based on the
62   * evaluation result.
63   * 
64   * @author Oliver Waeldrich
65   * 
66   */
67  public class SimpleGuaranteeEvaluator implements IGuaranteeEvaluator
68  {
69  
70      //
71      // constants
72      //
73      private static final String GUARANTEE_TERM_XPATH =
74          "declare namespace wsag='http://schemas.ggf.org/graap/2007/03/ws-agreement';" //$NON-NLS-1$
75              + "$this//wsag:GuaranteeTerm"; //$NON-NLS-1$
76  
77      //
78      // error message definitions
79      //
80      private static final String MSG_QC_FULFILLED = "SimpleGuaranteeEvaluator.QC_FULFILLED"; //$NON-NLS-1$
81  
82      private static final String MSG_VEXPR_TYPE_ERROR = "SimpleGuaranteeEvaluator.VALUE_EXPR_TYPE_ERROR"; //$NON-NLS-1$
83  
84      private static final String MSG_QC_NOT_FULFILLED = "SimpleGuaranteeEvaluator.QC_NOT_FULFILLED"; //$NON-NLS-1$
85  
86      private static final String MSG_QC_TYPE_ERROR = "SimpleGuaranteeEvaluator.QC_TYPE_ERROR"; //$NON-NLS-1$
87  
88      private static final String MSG_SLO_NO_CONTENT = "SimpleGuaranteeEvaluator.SLO_NO_CONTENT"; //$NON-NLS-1$
89  
90      private static final String MSG_SLO_TYPE_ERROR = "SimpleGuaranteeEvaluator.SLO_TYPE_ERROR"; //$NON-NLS-1$
91  
92      //
93      // private variable definitions
94      //
95      private static final Logger LOG = Logger.getLogger( SimpleGuaranteeEvaluator.class );
96  
97      private IAccountingSystem accountingSystem;
98  
99      private JexlEngine jexl;
100 
101     //
102     // open issues:
103     // - assessment intervals are not supported at all
104     //
105     //
106     // The AgreementPropertiesDocument holds all the information related to an agreement.
107     // This information is externally exposed as different properties of the agreement
108     // and can be queried vie the WSRF GetResourceProperty method. Internally, all this
109     // information is stored in one document.
110     //
111 
112     /**
113      * Default constructor
114      */
115     public SimpleGuaranteeEvaluator()
116     {
117         accountingSystem = new SimpleAccountingSystemLogger();
118 
119         //
120         // create JEXL engine and initialize wsag4j functions
121         //
122         jexl = new JexlEngine();
123         JEXLWSAG4JContext functions = new JEXLWSAG4JContext();
124         SLAFunctions funcImpl = new SLAFunctions();
125         functions.set( "wsag4j", funcImpl ); //$NON-NLS-1$
126         jexl.setFunctions( functions );
127     }
128 
129     /**
130      * @return the accountingSystem
131      * 
132      * @deprecated
133      */
134     public IAccountingSystem getAccountingSystem()
135     {
136         return accountingSystem;
137     }
138 
139     /**
140      * @param accountingSystem
141      *            the accountingSystem to set
142      * 
143      * @deprecated
144      */
145     public void setAccountingSystem( IAccountingSystem accountingSystem )
146     {
147         this.accountingSystem = accountingSystem;
148     }
149 
150     /**
151      * {@inheritDoc}
152      */
153     public GuaranteeEvaluationResultType evaluate( GuaranteeTermType guarantee, Map<String, Object> variables )
154         throws Exception
155     {
156         //
157         // initialize guarantee term evaluation result
158         //
159         GuaranteeEvaluationResultType evaluationResult = GuaranteeEvaluationResultType.Factory.newInstance();
160         evaluationResult.addNewDetails();
161         evaluationResult.getDetails().addNewGuarantee().set( guarantee );
162         evaluationResult.setName( guarantee.getName() );
163         evaluationResult.setType( SLOEvaluationResultType.SLO_NOT_DETERMINED );
164 
165         if ( guarantee.getBusinessValueList().isSetImportance() )
166         {
167             evaluationResult.setImportance( guarantee.getBusinessValueList().getImportance().intValue() );
168         }
169         else
170         {
171             evaluationResult.setImportance( 0 );
172         }
173 
174         GuaranteeTermStateType state = evaluationResult.getDetails().addNewGuaranteeState();
175         state.setTermName( guarantee.getName() );
176         state.setState( GuaranteeTermStateDefinition.NOT_DETERMINED );
177 
178         // Create a JEXL context
179         JEXLWSAG4JContext jc = new JEXLWSAG4JContext();
180         jc.setVars( variables );
181 
182         //
183         // create Guarantee States
184         //
185         if ( guarantee.isSetQualifyingCondition() )
186         {
187             //
188             // First, check whether the guarantee term will be evaluated or not.
189             // Therefore we need to check the qualifying condition, if present
190             //
191             // In the default implementation we assume that the qualifying condition
192             // is set as a string value.
193             //
194             XmlObject qcObject = guarantee.getQualifyingCondition();
195             String condition = XmlString.Factory.parse( qcObject.getDomNode() ).getStringValue();
196 
197             Expression qcExpr = jexl.createExpression( condition );
198             Object qcExprResult = qcExpr.evaluate( jc );
199             if ( qcExprResult instanceof Boolean )
200             {
201                 if ( ( (Boolean) qcExprResult ).booleanValue() )
202                 {
203                     LOG.info( Messages.formatString( MSG_QC_FULFILLED, guarantee.getName() ) );
204                 }
205                 else
206                 {
207                     LOG.info( Messages.formatString( MSG_QC_NOT_FULFILLED, guarantee.getName() ) );
208                     return evaluationResult;
209                 }
210             }
211             else
212             {
213                 String message =
214                     Messages.formatString( MSG_QC_TYPE_ERROR, new Object[] { guarantee.getName() } );
215                 throw new Exception( message );
216             }
217         }
218 
219         ServiceLevelObjectiveType slo = guarantee.getServiceLevelObjective();
220 
221         XmlObject sloCSL = null;
222         if ( slo.isSetKPITarget() )
223         {
224             sloCSL = slo.getKPITarget().getCustomServiceLevel();
225         }
226         else if ( slo.isSetCustomServiceLevel() )
227         {
228             sloCSL = slo.getCustomServiceLevel();
229         }
230         else
231         {
232             throw new Exception( Messages.getString( MSG_SLO_NO_CONTENT ) ); //$NON-NLS-1$
233         }
234 
235         String exprLit = XmlString.Factory.parse( sloCSL.getDomNode() ).getStringValue();
236         Expression expr = jexl.createExpression( exprLit );
237 
238         //
239         // Now evaluate the expression, getting the result
240         //
241         Object exprResult = expr.evaluate( jc );
242         if ( exprResult instanceof Boolean )
243         {
244             IAccountingContext context = new AccountingContext();
245             context.setGuarantee( guarantee );
246             context.setEvaluationResult( ( (Boolean) exprResult ).booleanValue() );
247 
248             if ( context.getEvaluationResult() )
249             {
250                 //
251                 // account a reward
252                 //
253                 state.setState( GuaranteeTermStateDefinition.FULFILLED );
254                 evaluationResult.setType( SLOEvaluationResultType.SLO_FULFILLED );
255 
256                 if ( guarantee.getBusinessValueList().getRewardArray().length > 0 )
257                 {
258                     CompensationType reward = guarantee.getBusinessValueList().getRewardArray( 0 );
259 
260                     XmlObject valueExpr = reward.getValueExpression();
261                     String expression = XmlString.Factory.parse( valueExpr.getDomNode() ).getStringValue();
262 
263                     Long value = evaluateBusinessValue( expression, jc );
264                     String unit = ( reward.getValueUnit() != null ) ? reward.getValueUnit() : ""; //$NON-NLS-1$
265 
266                     evaluationResult.addNewCompensation();
267                     evaluationResult.getCompensation().setValue( BigDecimal.valueOf( value ) );
268                     evaluationResult.getCompensation().setUnit( unit );
269                 }
270             }
271             else
272             {
273                 //
274                 // account a penalty
275                 //
276                 state.setState( GuaranteeTermStateDefinition.VIOLATED );
277                 evaluationResult.setType( SLOEvaluationResultType.SLO_VIOLATED );
278 
279                 if ( guarantee.getBusinessValueList().getPenaltyArray().length > 0 )
280                 {
281                     CompensationType penalty = guarantee.getBusinessValueList().getPenaltyArray( 0 );
282 
283                     XmlObject valueExpr = penalty.getValueExpression();
284                     String expression = XmlString.Factory.parse( valueExpr.getDomNode() ).getStringValue();
285 
286                     Long value = evaluateBusinessValue( expression, jc );
287                     String unit = ( penalty.getValueUnit() != null ) ? penalty.getValueUnit() : ""; //$NON-NLS-1$
288 
289                     evaluationResult.addNewCompensation();
290                     evaluationResult.getCompensation().setValue( BigDecimal.valueOf( value ) );
291                     evaluationResult.getCompensation().setUnit( unit );
292                 }
293             }
294 
295         }
296         else
297         {
298             String message = Messages.formatString( MSG_SLO_TYPE_ERROR, guarantee.getName() );
299             throw new Exception( message );
300         }
301 
302         return evaluationResult;
303     }
304 
305     private long evaluateBusinessValue( String exprLit, JexlContext jc ) throws Exception
306     {
307 
308         try
309         {
310             Expression expr = jexl.createExpression( exprLit );
311             Object exprResult = expr.evaluate( jc );
312 
313             if ( exprResult instanceof Double )
314             {
315 
316                 return ( (Double) exprResult ).longValue();
317             }
318 
319             if ( exprResult instanceof Integer )
320             {
321                 return ( (Integer) exprResult ).intValue();
322             }
323 
324             if ( exprResult instanceof String )
325             {
326                 return Long.parseLong( (String) exprResult );
327             }
328 
329             return Long.parseLong( exprResult.toString() );
330         }
331         catch ( NumberFormatException e )
332         {
333             throw new Exception( Messages.getString( MSG_VEXPR_TYPE_ERROR ), e );
334         }
335     }
336 
337     /**
338      * Selects all guarantees in an agreement properties document.
339      * 
340      * @param properties
341      *            the agreement properties document
342      * 
343      * @return the selected guarantees
344      */
345     public GuaranteeTermType[] selectGuaranteeTerms( AgreementPropertiesType properties )
346     {
347         //
348         // Find all guarantee terms, that are defined in this SLA
349         //
350         XmlObject[] result = properties.getTerms().selectPath( GUARANTEE_TERM_XPATH );
351 
352         GuaranteeTermType[] guarantees = new GuaranteeTermType[result.length];
353         for ( int i = 0; i < guarantees.length; i++ )
354         {
355             guarantees[i] = (GuaranteeTermType) result[i];
356         }
357 
358         return guarantees;
359     }
360 
361 }