blob: d71b98c443e2e9b595bb80c5d654f548f817a4aa [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.zest.demo.thirtyminutes;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.apache.zest.api.common.Optional;
import org.apache.zest.api.concern.ConcernOf;
import org.apache.zest.api.concern.Concerns;
import org.apache.zest.api.entity.EntityComposite;
import org.apache.zest.api.injection.scope.Structure;
import org.apache.zest.api.injection.scope.This;
import org.apache.zest.api.mixin.Mixins;
import org.apache.zest.api.property.Property;
import org.apache.zest.api.query.Query;
import org.apache.zest.api.structure.Module;
import org.apache.zest.api.unitofwork.UnitOfWork;
import org.apache.zest.api.unitofwork.UnitOfWorkFactory;
import org.apache.zest.api.value.ValueBuilder;
import org.apache.zest.api.value.ValueComposite;
import org.apache.zest.demo.tenminute.Confirmable;
import org.apache.zest.demo.tenminute.HasCustomer;
import org.apache.zest.demo.tenminute.HasLineItems;
import org.apache.zest.demo.tenminute.HasSequenceNumber;
import org.apache.zest.demo.tenminute.InventoryConcern;
import org.apache.zest.demo.tenminute.LineItem;
import org.apache.zest.demo.tenminute.PurchaseLimitConcern;
// START SNIPPET: 6
import static org.apache.zest.api.query.QueryExpressions.eq;
import static org.apache.zest.api.query.QueryExpressions.gt;
import static org.apache.zest.api.query.QueryExpressions.templateFor;
import org.apache.zest.api.query.QueryBuilder;
// END SNIPPET: 6
public class ThirtyMinutesDocs
{
Module module;
// START SNIPPET: 6
@Structure private UnitOfWorkFactory uowFactory; //Injected
// END SNIPPET: 6
{
// START SNIPPET: 6
UnitOfWork uow = uowFactory.currentUnitOfWork();
QueryBuilder<Order> builder = module.newQueryBuilder( Order.class );
String orderNumber = "12345";
HasSequenceNumber template = templateFor( HasSequenceNumber.class );
builder.where( eq( template.number(), orderNumber ) );
Query<Order> query = uow.newQuery( builder);
Iterator<Order> result = query.iterator();
if( result.hasNext() )
{
Order order = result.next();
}
else
{
// Deal with it wasn't found.
}
// END SNIPPET: 6
}
interface Report {
void addOrderToReport(Order order);
void addCustomerToReport(String customerName);
}
{
Report report = null;
UnitOfWork uow = module.currentUnitOfWork();
// START SNIPPET: 7
QueryBuilder<Order> builder = module.newQueryBuilder( Order.class );
Calendar cal = Calendar.getInstance();
cal.setTime( new Date() );
cal.roll( Calendar.DAY_OF_MONTH, -90 );
Date last90days = cal.getTime();
Order template = templateFor( Order.class );
builder.where( gt( template.createdDate(), last90days ) );
Query<Order> query = uow.newQuery(builder);
for( Order order : query )
{
report.addOrderToReport( order );
}
// END SNIPPET: 7
}
{
Report report = null;
UnitOfWork uow = module.currentUnitOfWork();
// START SNIPPET: 8
QueryBuilder<HasCustomer> builder = module.newQueryBuilder( HasCustomer.class );
Calendar cal = Calendar.getInstance();
cal.setTime( new Date() );
cal.roll( Calendar.MONTH, -1 );
Date lastMonth = cal.getTime();
Order template1 = templateFor( Order.class );
builder.where( gt( template1.createdDate(), lastMonth ) );
Query<HasCustomer> query = uow.newQuery(builder);
for( HasCustomer hasCustomer : query )
{
report.addCustomerToReport( hasCustomer.name().get() );
}
// END SNIPPET: 8
}
public interface Order
{
void addLineItem( LineItem item );
void removeLineItem( LineItem item );
void completed();
Property<Date> createdDate();
}
// START SNIPPET: 2
public interface HasAuditTrail<M>
{
AuditTrail<M> auditTrail();
}
public interface AuditTrail<M> extends Property<List<Action<M>>>
{}
public interface Action<T> extends ValueComposite // [2][3]
{
enum Type { added, removed, completed };
@Optional Property<T> item(); // [1]
Property<Type> action(); // [1]
}
public interface Trailable<M>
{
void itemAdded( M item );
void itemRemoved( M item );
void completed();
}
public class TrailableMixin<M>
implements Trailable<M>
{
private @This HasAuditTrail<M> hasTrail;
@Override
public void itemAdded( M item )
{
addAction( item, Action.Type.added );
}
@Override
public void itemRemoved( M item )
{
addAction( item, Action.Type.removed );
}
@Override
public void completed()
{
addAction( null, Action.Type.completed );
}
private Action<M> addAction( M item, Action.Type type )
{
ValueBuilder<Action> builder =
module.newValueBuilder(Action.class); // [4]
Action<M> prototype = builder.prototypeFor( Action.class );
prototype.item().set( item );
prototype.action().set( type );
Action instance = builder.newInstance();
hasTrail.auditTrail().get().add( instance );
return instance;
}
}
// END SNIPPET: 2
// START SNIPPET: 3
public abstract class OrderAuditTrailConcern
extends ConcernOf<Order>
implements Order
{
@This Trailable<LineItem> trail;
@Override
public void addLineItem( LineItem item )
{
next.addLineItem( item );
trail.itemAdded( item );
}
@Override
public void removeLineItem( LineItem item )
{
next.removeLineItem( item );
trail.itemRemoved( item );
}
@Override
public void completed()
{
next.completed();
trail.completed();
}
}
// END SNIPPET: 3
// START SNIPPET: 4
public class AuditTrailConcern
extends ConcernOf<InvocationHandler>
implements InvocationHandler
{
@This Trailable trail;
@Override
public Object invoke( Object proxy, Method m, Object[] args )
throws Throwable
{
Object retValue = next.invoke(proxy, m, args);
String methodName = m.getName();
if( methodName.startsWith( "add" ) )
{
trail.itemAdded( args[0] );
}
else if( methodName.startsWith( "remove" ) )
{
trail.itemRemoved( args[0] );
}
else if( methodName.startsWith( "complete" ) ||
methodName.startsWith( "commit" ) )
{
trail.completed();
}
return retValue;
}
}
// END SNIPPET: 4
// START SNIPPET: 5
@Concerns({
AuditTrailConcern.class,
PurchaseLimitConcern.class,
InventoryConcern.class
})
@Mixins( TrailableMixin.class )
public interface OrderEntity
extends Order, Confirmable,
HasSequenceNumber, HasCustomer, HasLineItems,
EntityComposite
{
}
// END SNIPPET: 5
}