/*
* Copyright 2005 Red Hat, Inc. and/or its affiliates.
*
* Licensed 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.drools.core.rule;
import org.drools.core.base.ClassObjectType;
import org.drools.core.spi.PatternExtractor;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class XpathBackReference {
public static final String BACK_REFERENCE_HEAD = "$back$ref$";
private final Pattern pattern;
private final List<Class<?>> backReferenceClasses;
private Map<String, Declaration> declarations = Collections.EMPTY_MAP;
private MapAdapter declarationMap;
public XpathBackReference( Pattern pattern, List<Class<?>> backReferenceClasses ) {
this.pattern = pattern;
this.backReferenceClasses = backReferenceClasses;
}
public void reset() {
declarations.clear();
}
public List<Class<?>> getBackReferenceClasses() {
return backReferenceClasses;
}
public Declaration getDeclaration(Pattern pattern, String id) {
if (!id.startsWith( BACK_REFERENCE_HEAD )) {
return null;
}
Declaration declaration = declarations.get(id);
if (declaration != null) {
return declaration;
}
int backRefPos = Integer.parseInt( id.substring( XpathBackReference.BACK_REFERENCE_HEAD.length() ) );
int relativeOffset = backReferenceClasses.size() - 1 - backRefPos;
declaration = new Declaration( id,
new PatternExtractor( new ClassObjectType( backReferenceClasses.get(backRefPos) ) ),
new RelativePattern( pattern, relativeOffset ),
true );
if (declarations == Collections.EMPTY_MAP) {
declarations = new HashMap<String, Declaration>();
}
declarations.put( id, declaration );
return declaration;
}
public Map<String, Declaration> getDeclarationMap() {
if (declarationMap == null) {
declarationMap = new MapAdapter();
}
return declarationMap;
}
public static class RelativePattern extends Pattern {
private final Pattern pattern;
private final int relativeOffset;
public RelativePattern( Pattern pattern, int relativeOffset ) {
this.pattern = pattern;
this.relativeOffset = relativeOffset;
}
@Override
public int getOffset() {
return pattern.getOffset() + relativeOffset;
}
}
public class MapAdapter implements Map<String, Declaration> {
@Override
public int size() {
return pattern.getDeclarations().size() + declarations.size();
}
@Override
public boolean isEmpty() {
return pattern.getDeclarations().isEmpty() && declarations.isEmpty();
}
@Override
public boolean containsKey( Object key ) {
return pattern.getDeclarations().containsKey(key) || declarations.containsKey(key);
}
@Override
public boolean containsValue( Object value ) {
return pattern.getDeclarations().containsValue(value) || declarations.containsValue( value );
}
@Override
public Declaration get( Object key ) {
Declaration declaration = pattern.getDeclarations().get(key);
if (declaration == null) {
declaration = getDeclaration(pattern, (String)key);
}
return declaration;
}
@Override
public Declaration put( String key, Declaration value ) {
return pattern.getDeclarations().put( key, value );
}
@Override
public Declaration remove( Object key ) {
return pattern.getDeclarations().remove( key );
}
@Override
public void putAll( Map<? extends String, ? extends Declaration> m ) {
pattern.getDeclarations().putAll(m);
}
@Override
public void clear() {
pattern.getDeclarations().clear();
declarations.clear();
}
@Override
public Set<String> keySet() {
return pattern.getDeclarations().keySet();
}
@Override
public Collection<Declaration> values() {
return pattern.getDeclarations().values();
}
@Override
public Set<Entry<String, Declaration>> entrySet() {
return pattern.getDeclarations().entrySet();
}
}
}