001 /* 002 Copyright (C) 2002 Julien van Malderen, Renaud Pawlak <renaud@aopsys.com> 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public License 015 along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 017 018 package org.objectweb.jac.aspects.integrity; 019 020 import java.util.Collection; 021 import java.util.Iterator; 022 import org.aopalliance.intercept.ConstructorInvocation; 023 import org.aopalliance.intercept.MethodInvocation; 024 import org.apache.log4j.Logger; 025 import org.objectweb.jac.core.AspectComponent; 026 import org.objectweb.jac.core.Interaction; 027 import org.objectweb.jac.core.Wrapper; 028 import org.objectweb.jac.core.rtti.ClassItem; 029 import org.objectweb.jac.core.rtti.ClassRepository; 030 import org.objectweb.jac.core.rtti.CollectionItem; 031 import org.objectweb.jac.core.rtti.MethodItem; 032 import org.objectweb.jac.core.rtti.RttiAC; 033 034 /** 035 * This wrapper provides a key scheme to limit fields 036 * doubles. 037 */ 038 039 public class PrimaryKeyWrapper extends Wrapper { 040 static final Logger logger = Logger.getLogger("integrity.primary"); 041 042 public PrimaryKeyWrapper(AspectComponent ac) { 043 super(ac); 044 } 045 046 /** 047 * This wrapping method checks if the added Object's fields match 048 * with an Object in the added collection, and throws an exception 049 * if there is one. 050 */ 051 public Object checkDoubles(Interaction interaction) throws Exception { 052 logger.debug("entering doubles-check for " + interaction.method); 053 054 CollectionItem coll = 055 ((MethodItem) interaction.method).getAddedCollection(); 056 057 String[] fieldsToComp = 058 (String[]) coll.getAttribute(RttiAC.PRIMARY_KEY); 059 060 Object addedObject = interaction.args[0]; 061 logger.debug("added value: " + addedObject); 062 063 Collection collection = coll.getActualCollection(interaction.wrappee); 064 065 Object[] newFields = new Object[fieldsToComp.length]; 066 ClassItem cli = ClassRepository.get().getClass(addedObject); 067 for (int i=0; i<fieldsToComp.length; i++) { 068 newFields[i] = 069 cli.getField(fieldsToComp[i]) 070 .getThroughAccessor(addedObject); 071 } 072 073 Iterator it = collection.iterator(); 074 while (it.hasNext()) { 075 Object object = it.next(); 076 if (((fieldsToComp == null) || (fieldsToComp.length == 0)) 077 && (object.equals(addedObject))) 078 throw new Exception( 079 "Collection " 080 + coll.getName() 081 + " already contains an element equals to " 082 + addedObject); 083 084 if ((fieldsToComp.length == 0) 085 || (!addedObject.getClass().equals(object.getClass()))) 086 continue; 087 088 int counter = 0; 089 cli = ClassRepository.get().getClass(object); 090 for (int i=0; i<fieldsToComp.length; i++) { 091 Object valueToTest = 092 cli.getField(fieldsToComp[i]).getThroughAccessor(object); 093 094 if (((valueToTest == null) && (newFields[i] == null)) 095 || ((valueToTest != null) 096 && (valueToTest.equals(newFields[i])))) 097 counter++; 098 else 099 break; 100 } 101 if (counter == fieldsToComp.length) { 102 String fields = ""; 103 for (int j = 0; j < fieldsToComp.length; j++) { 104 if (j > 0) 105 fields += ", "; 106 fields += fieldsToComp[j]; 107 } 108 throw new Exception( 109 "Collection " 110 + coll.getName() 111 + " already contains an element with fields { " 112 + fields 113 + " } equals to those in the added element"); 114 } 115 } 116 return proceed(interaction); 117 } 118 119 public Object invoke(MethodInvocation invocation) throws Throwable { 120 return checkDoubles((Interaction) invocation); 121 } 122 123 public Object construct(ConstructorInvocation invocation) 124 throws Throwable { 125 throw new Exception("Wrapper "+this+" does not support construction interception."); 126 } 127 }